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)すると、日付間のデータを取得する時間がなくても日付のみを取得できることがわかりました。

2013年 1 月 8 日としてDateTimePickers選択08/01/2013

クエリを見るためにメモを使用しました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 で の値を2013 年 8 月 1 日として設定すると、 の値が返されることDateTimePickersです。01/08/201308/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 は自動的に日付を datetime に変換し、必要な場所で実行する必要があります。

これを試すこともできます:

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'と、正確に「2013 年 8 月 1 日」の日付値を持つレコードのみが表示されます。

列のタイプが の場合、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'

これは少し奇妙に見えるかもしれませんが、指定された日付範囲のすべての日付スタンプが含まれます。

更新: これは、データ型でのみうまく機能し、 orDATETIMEでは機能しない汚いソリューションです。SMALLDATETIMEDATETIME2

私の観点からは、2 つのクリーンなソリューションがあります。

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

または日付と時刻を 2 つの列に分けます。もちろん、可能な場合に限り、1 日未満の範囲は必要ありません (たとえば、1 時間程度)。

于 2013-01-09T07:21:22.467 に答える
1

日付範囲のクエリは避けBETWEEN、m / d/yやd/m/yなどのあいまいな日付形式は避けてください。最終的に得られるクエリは次のようになります(デルファイコードでどのように到達するかは、私があなたに任せます)。

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

しかし、さらに良いことに、他の人が示唆しているように、パラメータを介して日付値を渡す必要があります。

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

(1日以外のケースが必要な場合は、2つのパラメーターを使用してください。)

日付/範囲クエリの背景と、これが必要な理由については、次を参照してください。

そして、なぜCONVERTを使用して日時から時間を削除するべきではないのですか?

于 2013-01-10T18:17:35.490 に答える