web-dev-qa-db-ja.com

時間部分を無視してDATETIMEとDATEを比較する

[date]DATETIME2(0)のタイプである2つのテーブルがあります。

2つのレコードを日付部分(日+月+年)のみで比較し、時間部分(時間+分+秒)を破棄する必要があります。

どうやってやるの?

134
abatishchev

SQL Server 2008でCASTを新しいDATEデータ型に使用して、日付部分のみを比較します。

IF CAST(DateField1 AS DATE) = CAST(DateField2 AS DATE)
231
marc_s

Marcの答えの小さな欠点は、両方の日付フィールドが型キャストされていることです。つまり、インデックスを活用することはできません。

そのため、日付フィールドのインデックスの恩恵を受けることができるクエリを作成する必要がある場合、次の(むしろ複雑な)アプローチが必要です。

  • インデックス付きの日付フィールド(DF1と呼ばれます)は、あらゆる種類の関数によって影響を受けないようにする必要があります。
  • そのため、DF1をDF2の日付と時刻の全範囲と比較する必要があります。
  • それは、DF2の日付部分からDF2の翌日の日付部分までです。
  • つまり(DF1 >= CAST(DF2 AS DATE)) AND (DF1 < DATEADD(dd, 1, CAST(DF2 AS DATE)))
  • NOTE:比較が> =であることが非常に重要です(等式)DF2の日付、および(厳密に)<DF2の翌日また、BETWEEN演算子は、両側で平等を許可するため機能しません。

PS:(古いバージョンのSQL Serverで)日付のみを抽出するもう1つの方法は、日付が内部的にどのように表されるかというトリックを使用することです。

  • 日付をフロートとしてキャストします。
  • 小数部分を切り捨てます
  • 値を日時に戻す
  • つまりCAST(FLOOR(CAST(DF2 AS FLOAT)) AS DATETIME)
58
Disillusioned

私は正しいとマークされた答えを支持しましたが。私はこれにつまずいた人のためにいくつかのことに触れたかった。

一般的に、日付の値のみで具体的にフィルタリングする場合。マイクロソフトでは、ymdまたはy-m-dの言語ニュートラル形式を使用することをお勧めします。

フォーム '2007-02-12'は、DATE、DATETIME2、およびDATETIMEOFFSETのデータ型についてのみ、言語に依存しないと見なされることに注意してください。

前述のアプローチを使用して日付比較を行うのは簡単です。次の不自然な例を考えてみましょう。

--112 is ISO format 'YYYYMMDD'
declare @filterDate char(8) = CONVERT(char(8), GETDATE(), 112)

select 
    * 
from 
    Sales.Orders
where
    CONVERT(char(8), OrderDate, 112) = @filterDate

完璧な世界では、フィルター処理された列に対する操作の実行は、SQL Serverがインデックスを効率的に使用することを妨げる可能性があるため、避ける必要があります。ただし、保存するデータが時刻ではなく日付のみに関係する場合は、時刻を午前0時にDATETIMEとして保存することを検討してください。なぜなら:

SQL Serverは、リテラルをフィルター処理された列の型に変換するときに、時刻部分が示されていない深夜を想定します。このようなフィルターが指定された日付のすべての行を返すようにする場合は、時刻を午前0時に設定してすべての値を保存する必要があります。

したがって、日付のみに関心があると仮定し、データをそのように保存します。上記のクエリは、次のように簡略化できます。

--112 is ISO format 'YYYYMMDD'
declare @filterDate char(8) = CONVERT(char(8), GETDATE(), 112)

select 
    * 
from 
    Sales.Orders
where
    OrderDate = @filterDate
4
pim

これを試すことができます

CONVERT(DATE, GETDATE()) = CONVERT(DATE,'2017-11-16 21:57:20.000')

私は次のコードでMS SQL 2014のそれをテストします

select case when CONVERT(DATE, GETDATE()) = CONVERT(DATE,'2017-11-16 21:57:20.000') then 'ok'
            else '' end
1
reza.cse08