Która metoda zapewnia najlepszą wydajność przy usuwaniu części czasu z pola daty i godziny w SQL Server?
a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)
lub
b) select cast(convert(char(11), getdate(), 113) as datetime)
Druga metoda przesyła jeszcze kilka bajtów w jedną stronę, ale może to nie być tak ważne, jak szybkość konwersji.
Oba wydają się być również bardzo szybkie, ale może być różnica prędkości w przypadku setek tysięcy lub więcej rzędów?
Czy jest też możliwe, że istnieją jeszcze lepsze metody na pozbycie się części czasu z datetime w SQL?
Odpowiedzi:
Ściśle mówiąc, metoda
a
wymaga najmniejszych zasobów:Udowodniono, że procesor jest mniej intensywny w tym samym łącznym czasie trwania milion wierszy o jeden za dużo ze zbyt dużą ilością czasu: Najskuteczniejszy sposób w SQL Server, aby uzyskać datę od daty i godziny?
Widziałem podobny test gdzie indziej z podobnymi wynikami.
Wolę DATEADD / DATEDIFF, ponieważ:
Przykład: Dlaczego moje wyrażenie CASE jest niedeterministyczne?
Edycja, październik 2011 r
W przypadku SQL Server 2008+ można CAST na
date
npCAST(getdate() AS date)
. Lub po prostu użyjdate
typu danych, więc nie ma czasu na usuwanie.Edytuj, styczeń 2012 r
Sprawdzony przykład elastyczności: trzeba obliczyć według zaokrąglonej godziny lub daty na serwerze SQL
Edytuj, maj 2012 r
Nie używaj tego w klauzulach WHERE itp. Bez zastanowienia: dodanie funkcji lub CAST do kolumny unieważnia użycie indeksu. Zobacz numer 2 tutaj: http://www.simple-talk.com/sql/t-sql-programming/ten-common-sql-programming-mistakes/
Teraz jest to przykład późniejszych wersji optymalizatora SQL Server poprawnie zarządzających CAST, ale ogólnie będzie to zły pomysł ...
Edycja, wrzesień 2018 r. Dla datetime2
źródło
DATE
raz dane jest obrzydliwie restrykcyjne, co pozwala to zrobić w odniesieniu do takich rzeczy jak DateAdd, DateDiff i interakcji z innymi typami danych data / czas. W takich przypadkachDATEADD()
podejście króluje.0218
2018
DATEDIFF
The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range datetime value
select DATEDIFF(dd, 0, convert(datetime2(0), '0218-09-12', 120))
SELECT DATEDIFF(dd, '19000101', convert(datetime2(0), '0218-09-12', 120))
W SQL Server 2008 możesz użyć:
źródło
datetime
nadate
, więc twoje rozwiązanie sprowadza się do sprawiedliwegoCONVERT(DATE,getdate())
, co zostało już zasugerowane więcej niż raz.CAST(GETDATE() AS DATE)
lub ściśle ANSI,CAST(CURRENT_TIMESTAMP AS DATE)
które moim zdaniem jest bezwartościowe. Zostań z pierwszym.Oczywiście jest to stary wątek, ale w celu uzupełnienia.
Z SQL 2008 możesz używać typu danych DATE, dzięki czemu możesz po prostu:
źródło
... nie jest dobrym rozwiązaniem, zgodnie z komentarzami poniżej.
Chciałbym usunąć tę odpowiedź, ale zostawię ją tutaj jako kontrprzykład, ponieważ uważam, że wyjaśnienie komentujących, dlaczego nie jest to dobry pomysł, jest nadal przydatne.
źródło
W SQL Server 2008 istnieje typ danych DATE (także typ danych TIME).
lub
źródło
Oto kolejna odpowiedź z innego duplikatu pytania:
Ta metoda magicznej liczby działa nieco szybciej niż metoda DATEADD. (Wygląda na to, że ~ 10%)
Czas procesora w kilku rundach miliona rekordów:
Pamiętaj jednak, że te liczby są prawdopodobnie nieistotne, ponieważ są już BARDZO szybkie. O ile nie miałem zestawów rekordów wynoszących 100 000 lub więcej, nie mogłem nawet odczytać Czasu Procesora powyżej zera.
Biorąc pod uwagę fakt, że DateAdd jest przeznaczony do tego celu i jest bardziej niezawodny, powiedziałbym, że użyj DateAdd.
źródło
'12:00:00.003'
która moim zdaniem jest znacznie lepsza.źródło
Naprawdę lubię:
120
Kod format będzie zmusić datę do standardu ISO 8601:Bardzo łatwy w użyciu w dplyr (
R
) i pandach (Python
)!źródło
STRZEC SIĘ!
Metoda a) ib) NIE zawsze ma taki sam wynik!
Wynik:
2014-01-01 00:00:00.000
Wynik:
2013-12-31 00:00:00.000
(Testowany na MS SQL Server 2005 i 2008 R2)
EDYCJA: Zgodnie z komentarzem Adama, nie może się to zdarzyć, jeśli odczytasz wartość daty z tabeli, ale może się tak zdarzyć, jeśli podasz wartość daty jako literał (przykład: jako parametr procedury składowanej wywoływanej przez ADO.NET).
źródło
DATETIME
kolumnie. Najwyższa dostępna to .997 Od: msdn.microsoft.com/en-us/library/ms187819.aspx zobaczysz, że wartości są zaokrąglone, aby mieć tysięczne miejsce na 0, 3 lub 7. OP nie zobaczy wartość z testu w ich tabelach.Najpierw usuń czas na wstawkach / aktualizacjach. Jeśli chodzi o konwersję w locie, nic nie jest w stanie pokonać funkcji zdefiniowanej przez użytkownika pod względem konserwacji:
Implementacja
date_only
może być dowolna - teraz jest abstrakcyjna, a wywoływanie kodu jest znacznie czystsze.źródło
WHERE DateAdd(DateDiff(Column)) = @DateValue
nie użyje indeksu. Z drugiej stronyWHERE Column >= dbo.UDF(@DateValue) AND Column < dbo.UDF(@DateValue + 1)
jest SARGable. Uważaj więc, jak to ująłeś.Zobacz to pytanie:
Jak obciąć datę i godzinę w programie SQL Server?
Cokolwiek robisz, nie używaj metody string . To najgorszy sposób, w jaki możesz to zrobić.
źródło
Odpowiedziałem już, ale źle to też tam wyrzucam ... to podobno również dobrze się sprawdza, ale działa to przez wyrzucenie przecinka (który przechowuje czas) z pływaka i zwrócenie tylko całej części (która jest datą)
drugi raz znalazłem to rozwiązanie ... złapałem ten kod
źródło
Ta metoda nie używa funkcji łańcuchowej.
Date
jest w zasadzie prawdziwym typem danych z cyframi po przecinku, które stanowią ułamek dnia.myślę, że będzie to szybsze niż wiele.
źródło
Dla mnie poniższy kod jest zawsze zwycięzcą:
źródło
wybierz CONVERT (char (10), GetDate (), 126)
źródło
Myślę, że chodzi Ci o
cast(floor(cast(getdate()as float))as datetime)
real ma tylko 32 bity i może stracić trochę informacji
To jest najszybsze
cast(cast(getdate()+x-0.5 as int)as datetime)
... choć tylko około 10% szybciej
(about 0.49 microseconds CPU vs. 0.58)
To było zalecane i zajmuje teraz ten sam czas w moim teście:
DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)
W SQL 2008 funkcja SQL CLR jest około 5 razy szybsza niż użycie funkcji SQL, przy 1,35 mikrosekundy w porównaniu z 6,5 mikrosekcjami, co wskazuje na znacznie niższy narzut wywołania funkcji dla funkcji SQL CLR w porównaniu z prostym SQL UDF.
W SQL 2005 funkcja SQL CLR jest 16 razy szybsza, według moich testów, w porównaniu z tą wolną funkcją:
źródło
Jak o
select cast(cast my_datetime_field as date) as datetime)
? Powoduje to tę samą datę, z czasem ustawionym na 00:00, ale pozwala uniknąć konwersji na tekst, a także pozwala uniknąć jawnego zaokrąglania liczb.źródło
Myślę, że jeśli trzymasz się tego ściśle
TSQL
, jest to najszybszy sposób na skrócenie czasu:Odkryłem, że ta metoda obcięcia jest o około 5% szybsza niż ta
DateAdd
metoda. Można to łatwo zmienić, aby zaokrąglić do najbliższego dnia w następujący sposób:źródło
Tutaj utworzyłem funkcję usuwania niektórych części datetime dla SQL Server. Stosowanie:
create function dbo.uf_RoundDateTime(@dt as datetime, @part as char) returns datetime as begin if CHARINDEX( @part, 'smhd',0) = 0 return @dt; return cast( Case @part when 's' then convert(varchar(19), @dt, 126) when 'm' then convert(varchar(17), @dt, 126) + '00' when 'h' then convert(varchar(14), @dt, 126) + '00:00' when 'd' then convert(varchar(14), @dt, 112) end as datetime ) end
źródło
Na wypadek, gdyby ktoś szukał tutaj wersji Sybase, ponieważ kilka powyższych wersji nie działało
źródło
cast
: W przypadku SQL Server 2008+ można dotychczas CAST. Lub po prostu użyj daty, więc nie ma czasu na usunięcie.datetime
nadate
: żaden z nich nie ma własnego formatu.Jeśli to możliwe, do takich specjalnych rzeczy lubię korzystać z funkcji CLR.
W tym przypadku:
źródło
Ja osobiście prawie zawsze korzystam z funkcji zdefiniowanych przez użytkownika do tego przez użytkownika, jeśli mamy do czynienia z SQL Server 2005 (lub niższą wersją), należy jednak zauważyć, że istnieją szczególne wady korzystania z UDF, szczególnie jeśli stosuje się je do klauzul WHERE (patrz poniżej i komentarze do tej odpowiedzi w celu uzyskania dalszych szczegółów). Jeśli używasz programu SQL Server 2008 (lub nowszego) - patrz poniżej.
W rzeczywistości dla większości baz danych, które tworzę, dodaję te UDF tuż przy początku, ponieważ wiem, że istnieje 99% szansa, że będę ich potrzebować wcześniej czy później.
Tworzę jeden dla „tylko daty” i „tylko czasu” (chociaż „tylko data” jest zdecydowanie najczęściej używanym z nich).
Oto kilka linków do różnych UDF związanych z datą:
Najważniejsze funkcje daty, godziny i daty i godziny w programie SQL Server
Uzyskaj funkcję tylko daty
Ten ostatni link pokazuje nie mniej niż 3 różne sposoby, aby data była tylko częścią pola daty i godziny, i wymienia niektóre zalety i wady każdego podejścia.
Jeśli używasz UDF, należy zauważyć, że powinieneś unikać używania UDF jako części klauzuli WHERE w zapytaniu, ponieważ to znacznie pogorszy wydajność zapytania. Głównym tego powodem jest to, że użycie UDF w klauzuli WHERE powoduje, że klauzula ta nie podlega wymianie , co oznacza, że SQL Server nie może już używać indeksu z tą klauzulą w celu poprawy szybkości wykonywania zapytania. Odnosząc się do własnego użycia UDF, często użyję kolumny „surowej” daty w klauzuli WHERE, ale zastosuję UDF do kolumny WYBRANE. W ten sposób UDF jest stosowany tylko do filtrowanego zestawu wyników, a nie do każdego wiersza tabeli jako część filtru.
Oczywiście absolutnie najlepszym podejściem do tego jest użycie programu SQL Server 2008 (lub nowszego) i oddzielenie dat i godzin , ponieważ silnik bazy danych SQL Server natywnie dostarcza poszczególne komponenty daty i godziny i może efektywnie sprawdzać je niezależnie bez potrzeby stosowania UDF lub innego mechanizmu do wyodrębnienia części daty lub godziny z typu złożonego typu data-godzina.
źródło
WHERE DateColumn >= {TimeTruncatingExpression}(@DateValue) AND DateColumn < {TimeTruncatingExpression}(@DateValue + 1)
. Czułem, że muszę coś powiedzieć, ponieważ powiedziałeś: „Prawie zawsze używam UDF”, nie wyjaśniłem żadnej z wad ani sposobu na zapytanie SARGable oparte tylko na dacie.Użyłbym:
W ten sposób skutecznie tworzysz nowe pole z pola daty, które już masz.
źródło
datetime
wartości, konwertowanie ich na ciągi, łączenie ich razem i wreszcie przekształcanie wyniku z powrotemdatetime
jest lepsze niż np. Wykonywanie bezpośrednich obliczeń na oryginaledatetime
( metodaDATEADD
/DATEDIFF
)?MM
iDD
? W SQL Server nie ma takich funkcji.