Porównaj DATETIME i DATE, ignorując część czasu

151

Mam dwie tabele, w których kolumna [date]jest typem DATETIME2(0).

Muszę porównać dwa rekordy tylko według części daty (dzień + miesiąc + rok), odrzucając części czasu (godziny + minuty + sekundy).

Jak mogę to zrobić?

abatishchev
źródło

Odpowiedzi:

252

Użyj CASTdo nowego DATEtypu danych w SQL Server 2008, aby porównać tylko część daty:

IF CAST(DateField1 AS DATE) = CAST(DateField2 AS DATE)
marc_s
źródło
61

Niewielką wadą odpowiedzi Marca jest to, że oba pola daty zostały umieszczone w typoszeregu, co oznacza, że ​​nie będzie można wykorzystać żadnych indeksów.

Tak więc, jeśli istnieje potrzeba napisania zapytania, które może skorzystać z indeksu w polu daty, konieczne jest następujące (raczej zawiłe) podejście.

  • Indeksowane pole daty (nazwij je DF1) nie może być naruszane przez żadną funkcję.
  • Więc musisz porównać DF1 z pełnym zakresem wartości daty i godziny dla dnia DF2.
  • To znaczy od części daty DF2 do części daty w dniu następującym po DF2.
  • To znaczy (DF1 >= CAST(DF2 AS DATE)) AND (DF1 < DATEADD(dd, 1, CAST(DF2 AS DATE)))
  • UWAGA : Bardzo ważne jest, aby porównanie było > = (dozwolona równość) z datą DF2 i (ściśle) < dzień po DF2. Również operator BETWEEN nie działa, ponieważ pozwala na równość po obu stronach.

PS: Innym sposobem wyodrębnienia samej daty (w starszych wersjach SQL Server) jest użycie sztuczki polegającej na tym, jak data jest reprezentowana wewnętrznie.

  • Przerzuć datę jako pływak.
  • Obetnij część ułamkową
  • Odrzuć wartość z powrotem do daty i godziny
  • To znaczy CAST(FLOOR(CAST(DF2 AS FLOAT)) AS DATETIME)
Rozczarowany
źródło
5

Chociaż głosowałem za odpowiedzią oznaczoną jako poprawna. Chciałem poruszyć kilka rzeczy dla każdego, kto się na to natknie.

Ogólnie rzecz biorąc, jeśli filtrujesz wyłącznie według wartości daty . Firma Microsoft zaleca używanie neutralnego językowo formatu ymdlub y-m-d.

Należy zauważyć, że formularz „2007-02-12” jest uważany za neutralny językowo tylko w przypadku typów danych DATE, DATETIME2 i DATETIMEOFFSET.

Porównanie dat przy użyciu wyżej wymienionego podejścia jest proste. Rozważmy następujący, wymyślony przykład.

--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

W idealnym świecie należy unikać wykonywania jakichkolwiek operacji na kolumnie filtrowanej, ponieważ może to uniemożliwić programowi SQL Server wydajne korzystanie z indeksów. To powiedziawszy, jeśli dane, które przechowujesz, dotyczą tylko daty, a nie godziny, rozważ przechowywanie DATETIMEo północy jako godzinie. Ponieważ:

Gdy SQL Server konwertuje literał na typ kolumny filtrowanej, przyjmuje północ, gdy część czasu nie jest wskazana. Jeśli chcesz, aby taki filtr zwracał wszystkie wiersze z określonej daty, musisz upewnić się, że wszystkie wartości są przechowywane z północą jako godziną.

Zatem zakładając, że interesuje Cię tylko data i przechowujesz swoje dane jako takie. Powyższe zapytanie można uprościć do:

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

select 
    * 
from 
    Sales.Orders
where
    OrderDate = @filterDate
pimbrouwers
źródło
3

Możesz spróbować tego

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

Testuję to dla MS SQL 2014, wykonując poniższy kod

select case when CONVERT(DATE, GETDATE()) = CONVERT(DATE,'2017-11-16 21:57:20.000') then 'ok'
            else '' end
reza.cse08
źródło
-3

Aby porównać dwie daty, takie jak MM / DD / RRRR do MM / DD / RRRR . Zapamiętaj Typ kolumny Field musi być typu dateTime. Przykład: columnName: PAYMENT_DATE dataType: DateTime .

potem możesz go łatwo porównać. Zapytanie to:

select  *  from demo_date where date >= '3/1/2015' and date <=  '3/31/2015'.

To bardzo proste ...... Przetestowało to .....

pankaj
źródło
To nie do końca odpowiada na pytanie. Pyta przez miesiąc, a nie dzień.
Curtis Yallop,
W przypadku zapytania z marca: jeśli data to „31.03.2015” i godzina 13:00, nie zostanie znaleziona. Należy użyć <„4/1/2015”.
Curtis Yallop,
Rozważ także użycie międzynarodowego formatu daty „2015-03-01”. W Kanadzie (i wielu innych miejscach) oficjalnym formatem jest DD / MM / RRRR, co sprawia, że ​​oba formaty są niejednoznaczne i problematyczne.
Curtis Yallop,
Ta odpowiedź nie dotyczy 2 tabel, jak żądano w pytaniu.
Curtis Yallop,
Tak, zgadzam się, ale tylko udowadniam rozwiązanie, a nie rozwiązanie międzynarodowe .. musisz zmienić jakąś kolejność ...
pankaj