Zaokrąglanie SQL DateTime do północy

81

Mam mały problem z zapytaniem SQL. Używam funkcji GETDATE, ale powiedzmy, że wykonuję skrypt o 17:00, a rekordy pojawią się między 17.12.2011 a 17.12.2011 17:00. Jak mogę to zrobić, aby wyciągać rekordy z całego 12/12/2011 - 12/18/2011 w zasadzie ignorować czas.

Mój skrypt:

WHERE Orders.OrderStatus = 'Shipped'  
AND Orders.ShipDate > (GETDATE()-6)  
henryaaron
źródło

Odpowiedzi:

114

W SQL Server 2008 i nowszych wersjach można rzutować na DateTimea Date, co usuwa element czasu.

WHERE Orders.OrderStatus = 'Shipped'  
AND Orders.ShipDate >= (cast(GETDATE()-6 as date))  

W SQL Server 2005 i starszych możesz użyć:

WHERE Orders.OrderStatus = 'Shipped'  
AND Orders.ShipDate >= DateAdd(Day, Datediff(Day,0, GetDate() -6), 0)
DaveShaw
źródło
1
Mam ten typ Data nie jest zdefiniowanym typem systemu.
henryaaron,
2
Chyba nie używasz SQL 2008 :)
DaveShaw,
@ user1090389 dlatego umieściłem opcję konwersji ciągów; D
Bassam Mehanni
@DaveShaw - Missing a DATEADD in there
MatBailie
Przepraszamy, @Dems Dave's wygląda na mniej skomplikowane
henryaaron,
54

Oto najprostsza rzecz, jaką znalazłem

-- Midnight floor of current date

SELECT Convert(DateTime, DATEDIFF(DAY, 0, GETDATE()))

DATEDIFF zwraca całkowitą liczbę dni przed lub od 1900-1-1, a funkcja Convert Datetime obligatoryjnie przywraca tę datę o północy.

Ponieważ DateDiff zwraca liczbę całkowitą, możesz użyć dodawania lub odejmowania dni, aby uzyskać właściwe przesunięcie.

SELECT Convert(DateTime, DATEDIFF(DAY, 0, GETDATE()) + @dayOffset)

To nie jest zaokrąglanie, to ucinanie ... Ale myślę, że o to się prosi. (Aby zaokrąglić, dodać jeden i obciąć ... i to też nie jest zaokrąglanie, to sufit, ale najprawdopodobniej to, co chcesz. Aby naprawdę zaokrąglić, dodaj 0,5 (czy to działa?) I obetnij.

Okazuje się, że możesz dodać .5 do GetDate () i działa zgodnie z oczekiwaniami.

-- Round Current time to midnight today or midnight tomorrow

SELECT Convert(DateTime, DATEDIFF(DAY, 0, GETDATE() + .5))

Wykonałem wszystkie testy na SQL Server 2008, ale myślę, że te funkcje mają zastosowanie również w 2005 roku.

Darrel Lee
źródło
Działa to w 2k5 właśnie to przetestowałem. where [ScanDate] >= convert(datetime, datediff(day, 0, getdate())) and [ScanDate] < convert(datetime, datediff(day, -1, getdate()))
nulltron
9
--
-- SQL DATEDIFF getting midnight time parts 
--
SELECT GETDATE() AS Now, 
   Convert(DateTime, DATEDIFF(DAY, 0, GETDATE())) AS MidnightToday,
   Convert(DateTime, DATEDIFF(DAY, -1, GETDATE())) AS MidnightNextDay,
   Convert(DateTime, DATEDIFF(DAY, 1, GETDATE())) AS MidnightYesterDay
go
Now                   MidnightToday          MidnightNextDay        MidnightYesterDay     
 --------------------  ---------------------  ---------------------  --------------------- 
 8/27/2014 4:30:22 PM  8/27/2014 12:00:00 AM  8/28/2014 12:00:00 AM  8/26/2014 12:00:00 AM 
edvox1138
źródło
5
SELECT getdate()

Wynik: 2012-12-14 16: 03: 33,360

SELECT convert(datetime,convert(bigint, getdate()))

Wynik 2012-12-15 00: 00: 00.000

Jeremy Atkinson
źródło
1
Dzięki za opinie. Co starałem się podkreślić, że konwersja na bigint iz powrotem zaokrągla za Ciebie.
Jeremy Atkinson
1
Ten kod zaokrągla go do północy na koniec dnia, jeśli godzina jest po południu, co powoduje, że jest to błędne przez pół dnia.
ChrisM
Korzystanie z tej metody może mieć wpływ na wydajność później w przypadku większych zestawów danych.
Taco タ コ ス
3

Jak wspomniał @BassamMehanni, w SQL Server 2008 można rzutować jako DATE ...

SELECT
  *
FROM
  yourTable
WHERE
      dateField >= CAST(GetDate() - 6 AS DATE)
  AND dateField <  CAST(GetDate() + 1 AS DATE)

Drugi warunek może być w rzeczywistości sprawiedliwy GetDate(), ale pokazuję ten format jako przykład, Less Than DateXaby uniknąć konieczności rzutowania dateField również na DATĘ, co znacznie poprawia wydajność.


Jeśli masz rok 2005 lub mniej, możesz użyć tego ...

SELECT
  *
FROM
  yourTable
WHERE
      dateField >= DATEADD(DAY, DATEDIFF(DAY, 0, GetDate()) - 6, 0)
  AND dateField <  DATEADD(DAY, DATEDIFF(DAY, 0, GetDate()) + 1, 0)
MatBailie
źródło
3

Spróbuj tego użyć.

WHERE Orders.OrderStatus = 'Shipped'  
AND Orders.ShipDate >= CONVERT(DATE, GETDATE())
UttamG
źródło
1

To może wyglądać na tanie, ale działa na mnie

SELECT CONVERT (DATETIME, LEFT (CONVERT (VARCHAR, @ dateFieldOrVariable, 101), 10) + '00: 00: 00.000')

Jean-Louis Gervais
źródło
1

Możesz przekonwertować datę i godzinę na datę, a następnie z powrotem na datę i godzinę. Spowoduje to zresetowanie sygnatury czasowej.

wybierz getdate () --2020-05-05 13: 53: 35.863

wybierz rzutowanie (rzutowanie (GETDATE () jako data) jako datetime) --2020-05-05 00: 00: 00.000
Ben
źródło
0

Zwyklę robię

SELECT *
FROM MyTable
WHERE CONVERT(VARCHAR, MyTable.dateField, 101) = CONVERT(VARCHAR, GETDATE(), 101)

jeśli używasz programu SQL SERVER 2008, możesz to zrobić

SELECT *
FROM MyTable
WHERE CAST(MyTable.dateField AS DATE) = CAST(GETDATE() AS DATE)

Mam nadzieję że to pomoże

Bassam Mehanni
źródło
3
Jeśli użyjesz pierwszego przykładu, pozbawiasz optymalizatora możliwości używania indeksów itp. Używanie funkcji String do wykonywania arytmetyki i porównań dat jest bardzo złym pomysłem. Nie powinno się o tym nigdy (imo) nawet wspominać, to taka kiepska opcja.
MatBailie,
Nie musisz tego robić, jeśli używasz SQL Server 2008, w przeciwnym razie nie jestem pewien, jak inaczej mógłbyś to zrobić w SQL Server 2000/2005, przykład byłby wdzięczny, dzięki.
Bassam Mehanni,
Aby być uczciwym. Obie opcje niszczą zdolność optmizera do używania indeksów. Należy wykonać i funkcjonować w kolumnie predykatu filtru. Obejmuje to odlewy.
pim
0

Mógłbyś zaokrąglić czas.

Użycie ROUNDponiżej zaokrągli go do północy.

WHERE Orders.OrderStatus = 'Shipped'  
AND Orders.ShipDate >  CONVERT(datetime, (ROUND(convert(float, getdate()-6.5),0)))
Krzyżmo
źródło