4

次の 2 つのクエリは、異なる結果を返しています。違いは日付の時間部分の処理方法に関係していることは理解していますが、なぜこのように機能するのですか?

// QUERY ONE
select top 3 OrderDate
from Orders
where OrderDate >= '2013-11-01 04:00'
and OrderDate <= '2013-11-30 05:00'
order by OrderDate

// RESULTS
// 2013-11-01
// 2013-11-01
// 2013-11-01

// QUERY TWO
exec sp_executesql
    N'select top 3 OrderDate
      from Orders
      where OrderDate >= @p__linq__0
      and OrderDate <= @p__linq__1
      order by OrderDate',
    N'@p__linq__0 datetime2(7),@p__linq__1 datetime2(7)',
    @p__linq__0='2013-11-01T04:00:00',
    @p__linq__1='2013-11-30T05:00:00'

// RESULTS
// 2013-11-02
// 2013-11-02
// 2013-11-02

アップデート

sp_executesql に渡されるパラメーターの型を「datetime」ではなく「date」に変更すると、結果は同じになります。

// QUERY THREE
exec sp_executesql
N'select top 3 OrderDate
  from Orders
  where OrderDate >= @p__linq__0
  and OrderDate <= @p__linq__1
  order by OrderDate',
N'@p__linq__0 date,@p__linq__1 date',
@p__linq__0='2013-11-01T04:00:00',
@p__linq__1='2013-11-30T05:00:00'

// RESULTS
// 2013-11-01
// 2013-11-01
// 2013-11-01
4

3 に答える 3

6

データ型の優先順位は、日付として始まるテーブル内のデータを取得し、datetime2(7) として比較します。したがって、動的 SQL バージョンは実際にこれを実行しています。

WHERE column_as_datetime2 >= @parameter_as_datetime2

したがって、は以上で2013-11-01 00:00:00.0000000ない2013-11-01 04:00:00.0000000ため、11 月 1 日からの行は除外されます。

最も実用的な解決策は、DATEパラメーターを使用することです (パラメーターは基本的なデータ型と一致する必要があるため、推奨されます)、および/またはそれらと一緒に時間値を渡すことを停止します。これらを試してください:

USE tempdb;
GO

CREATE TABLE dbo.Orders(OrderDate DATE);

INSERT dbo.Orders VALUES('2013-11-01'),('2013-11-01'),('2013-11-01'),
  ('2013-11-02'),('2013-11-02'),('2013-11-02');

exec sp_executesql N'select top 3 OrderDate
      from Orders
      where OrderDate >= @p__linq__0
      and OrderDate <= @p__linq__1
      order by OrderDate;
select top 3 OrderDate
      from Orders
      where OrderDate >= @p2
      and OrderDate <= @p3
      order by OrderDate;
select top 3 OrderDate
      from Orders
      where OrderDate >= @p4
      and OrderDate <= @p5
      order by OrderDate;',
    N'@p__linq__0 datetime2(7),@p__linq__1 datetime2(7),
      @p2 datetime2(7),@p3 datetime2(7),@p4 date,@p5 date',
    @p__linq__0='2013-11-01T04:00:00',
    @p__linq__1='2013-11-30T05:00:00',
    @p2='2013-11-01T00:00:00', -- note no time
    @p3='2013-11-30T00:00:00', -- note no time
    @p4='2013-11-01',
    @p5='2013-11-30';

結果:

OrderDate
----------
2013-11-02
2013-11-02
2013-11-02

OrderDate
----------
2013-11-01
2013-11-01
2013-11-01

OrderDate
----------
2013-11-01
2013-11-01
2013-11-01
于 2013-11-05T16:48:25.230 に答える
4

OrderDateのタイプdateは ではなく に違いありませんdatetime。だからあなたがこれをするとき

where OrderDate >= '2013-11-01 04:00'

ではなくに変換'2013-11-01 04:00'されるため、時間情報が失われます。したがって、最初のクエリの条件は と解釈されます。これは本当です。datedatetime'2013-11-01 00:00:00' >= '2013-11-01 00:00:00'

2 番目のクエリで、SP はdatetime、時間情報を持つ type のパラメーターを受け取ります。'2013-11-01 00:00:00' >= '2013-11-01 04:00:00'そこにある条件は、どちらが false であるかと解釈されます。

最初のクエリで同じ動作が必要な場合datetimeは、文字列の代わりに変数を使用します。

declare @d1 datetime
declare @d2 datetime
set @d1 = '2013-11-01 04:00'
set @d2 = '2013-11-30 05:00'

select top 3 OrderDate
from Orders
where OrderDate >= @d1
and OrderDate <= @d2
order by OrderDate
于 2013-11-05T16:43:42.067 に答える
0

これを試して ...

DECLARE @p__linq__0_R datetime2(7) = '2013-11-01T04:00:00'
DECLARE @p__linq__1_R datetime2(7) = '2013-11-30T05:00:00'

DECLARE @sql NVARCHAR(MAX);

SET @sql =  N'select top 3 OrderDate
      from Orders
      where OrderDate >= @p__linq__0_s
      and OrderDate <= @p__linq__1_s
      order by OrderDate'

exec sp_executesql @sql,
    N'@p__linq__0_s datetime2(7),@p__linq__1_s datetime2(7)',
    @p__linq__0_s =@p__linq__0_R,
    @p__linq__1_s=@p__linq__1_R

編集
列がDatetime2ではなくDatetimeのみの場合、Datetime2はdatetimeよりも優先順位の高いデータ型であるため、SQLサーバーはDatetimeデータ型の列で暗黙的な変換を行っています。2 つの値を比較するには、SQL サーバーは値が同じデータ型であると想定します。多分これが問題の原因です。値を比較するときに、datetime 列を datetime2 にキャストできます。

于 2013-11-05T16:32:41.430 に答える