1

我正在使用 SQL Server 2005 Management Studio Express 和 Delphi 2010。Fecha_hora= Date_Time 是smalldatetime.

我的日期格式是dd/mm/yyy

我表中的日期保存如下:

08/01/2013 11:22:00 a.m.

我在 Delphi 中有这个查询,以了解给定一段时间内的销售额在哪个时间段更高;天/月,在这种情况下,我在 2013 年 1 月 8 日的同一天进行测试:

  conect.Q_total_hora.Active:=false;
  conect.Q_total_hora.SQL.Clear;
  conect.Q_total_hora.SQL.Add('select datepart(hh, fecha_hora) as Hora, sum(Total) as Venta, a.tipo as Tipo');
  conect.Q_total_hora.SQL.Add('from ventas v join articulos a on v.id_articulo=a.id_articulo');
  conect.Q_total_hora.SQL.Add('where tipo='+char(39)+DBLUCB_tipo.Text+char(39)+' and cast(Convert(varchar(10), fecha_hora, 112) as datetime) between'+char(39)+DateToStr(DateTimePicker_fecha1.Date)+char(39)+ 'and'+char(39)+DateToStr(DateTimePicker_fecha2.Date)+char(39));
  conect.Q_total_hora.SQL.Add('group by datepart(hh,fecha_hora), a.tipo order by datepart(hh,fecha_hora) ');
  conect.Q_total_hora.Active:=true;

我之所以使用cast(Convert(varchar(10), fecha_hora, 112) as datetime),是因为我在互联网上发现这样我只能检索日期,而没有时间检索日期之间的数据。

DateTimePickers我选择08/01/2013作为 2013 年 1 月 8 日

我用备忘录查看查询memo1.Text:=conect.Q_total_hora.Text;

我收到的查询是:

select datepart(hh, fecha_hora) as Hora, sum(Total) as Venta, a.tipo as Tipo
from ventas v join articulos a on v.id_articulo=a.id_articulo
where tipo='Burrito Grande' and cast(Convert(varchar(10), fecha_hora, 112) as datetime) between'08/01/2013'and'08/01/2013'
group by datepart(hh,fecha_hora), a.tipo order by datepart(hh,fecha_hora)

我遇到的问题是,当我在 SQL Server Mgmt Studio 中运行此查询时,它返回值,但在 Delphi 中不返回,并且在 Delphi 中,如果我将 的值设置DateTimePickers01/08/20132013 年 8 月 1 日,它会返回08/01/2012.

据我所知(而且我知道的不多......)当我向 SQL Server 发送查询时,就像我用 SQL 编写它......为什么如果我将日期08/01/2013作为字符串发送它不返回任何东西?

先感谢您。我不擅长数据库,大多数东西我在互联网上寻找它们^^

4

4 回答 4

9

您可以避免所有这些问题,并使用参数化查询编写非常简洁的代码。

试试这个

  conect.Q_total_hora.Active:=false;
  conect.Q_total_hora.SQL.Clear;
  conect.Q_total_hora.SQL.Add('select datepart(hh, fecha_hora) as Hora, sum(Total) as Venta, a.tipo as Tipo');
  conect.Q_total_hora.SQL.Add('from ventas v join articulos a on v.id_articulo=a.id_articulo');
  conect.Q_total_hora.SQL.Add('where tipo=:tipo and fecha_hora between :fecha1 and :fecha2');
  conect.Q_total_hora.SQL.Add('group by datepart(hh,fecha_hora), a.tipo order by datepart(hh,fecha_hora) ');
  conect.Q_total_hora.Prepared:=True;
  conect.Q_total_hora.ParamByName('tipo').AsString   := DBLUCB_tipo.Text;
  conect.Q_total_hora.ParamByName('fecha1').AsDateTime := DateTimePicker_fecha1.Date;
  conect.Q_total_hora.ParamByName('fecha2').AsDateTime := DateTimePicker_fecha2.Date;
  conect.Q_total_hora.Open;
于 2013-01-09T01:52:09.133 回答
2

试试这个:

conect.Q_total_hora.SQL.Add('where tipo='+char(39)+DBLUCB_tipo.Text+char(39)+' and  fecha_hora between '+char(39)+DateToStr(DateTimePicker_fecha1.Date)+char(39)+ ' and '+char(39)+DateToStr(DateTimePicker_fecha2.Date)+char(39));

这应该看起来像:

where tipo='Burrito Grande' and fecha_hora between '08/01/2013' and '08/01/2013'

SQL 应该自动将日期转换为日期时间并执行您想要的操作。

你也可以试试这个:

where tipo='Burrito Grande' and month(fecha_hora) = 8 and year(fecha_hora) = 2013 and day(fecha_hora) = 1
于 2013-01-09T00:55:20.020 回答
2

如果您使用该术语BETWEEN '08/01/2013' and '08/01/2013',您确实只会看到日期值恰好为 '08/01/2013' 的记录。

如果列是类型date,您将得到您想要的,但由于您的列类型是datetime,内容 '08/01/2013 11:22' 不在 '08/01/2013 00:00:00' 和 '08' 之间/01/2013 00:00:00' 并因此被忽略。

查询日期时间列时,使用这样的模式

...
where DateTimeCol between '<StartDate>' and '<EndDate> 23:59:59,997'

这可能看起来有点奇怪,但将包括给定日期范围内的所有日期戳。

更新:这是一个肮脏的解决方案,它只适用于数据类型DATETIME,但不适用于SMALLDATETIMEor DATETIME2

从我的角度来看,有两种干净的解决方案:要么使用

where (DateTimeCol>='<StartDate>') 
  and (DateTimeCol <'<The day following the EndDate>')

或将日期和时间分开到两列。当然,只有在可能的情况下并且不需要小于一天的范围(例如一小时左右)。

于 2013-01-09T07:21:22.467 回答
1

您应该避免BETWEEN日期范围查询,以及避免任何模棱两可的日期格式,例如 m/d/y 或 d/m/y。你最终得到的查询应该是这样的(你如何在你的 delphi 代码中到达那里,我将留给你):

WHERE fecha_hora >= '20130801' AND fecha_hora < '20130802'

但更好的是,正如其他人所建议的那样,您应该通过参数传递日期值,例如

WHERE fecha_hora >= @date_param AND fecha_hora < DATEADD(DAY, 1, @date_param)

(如果您需要除单日以外的其他情况,请使用两个参数。)

有关日期/范围查询的更多背景信息以及为什么应该这样做:

以及为什么不应该使用 CONVERT 从日期时间中删除时间:

于 2013-01-10T18:17:35.490 回答