Najlepsze podejście do usunięcia części czasu z datetime w SQL Server

514

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?

Stephen Perelson
źródło
1
Wypróbowałem to na milionie rekordów na jednej z moich tabel produkcyjnych i nie udało mi się uzyskać dokładnego odczytu wydajności. Obie metody zwróciły jednak dokładnie taką samą ilość danych.
Stephen Perelson
9
Oto, co znalazłem w 18 000 000 wierszy (SQL Server 2008): Metoda b jest około 24% wolniejsza niż metoda a. CAST (FLOOR (CAST (getdate () AS FLOAT)) AS AS DATETIME) jest o 3,5% wolniejszy niż metoda a. Metoda a wydaje się być zwycięzcą pod względem wydajności. Dziękuję wszystkim za wspaniałe odpowiedzi.
Stephen Perelson
46
Dlaczego, do cholery, SQL nie ma wbudowanej funkcji, aby to zrobić? !!
Gary McGill
10
Nowy typ danych DATE w SQL 2008 da sobie z tym radę.
Philip Kelley,

Odpowiedzi:

557

Ściśle mówiąc, metoda awymaga najmniejszych zasobów:

a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)

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

Edycja, październik 2011 r

W przypadku SQL Server 2008+ można CAST na datenp CAST(getdate() AS date). Lub po prostu użyj datetypu 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

DECLARE @datetime2value datetime2 = '02180912 11:45' --this is deliberately within datetime2, year 0218
DECLARE @datetime2epoch datetime2 = '19000101'

select DATEADD(dd, DATEDIFF(dd, @datetime2epoch, @datetime2value), @datetime2epoch)
gbn
źródło
3
@David Sopko dla edycji z października 2011, a następnie kod będzie: wybierz obsadę (GETDATE () jako datę)
Choco Smith
1
W nowszych wersjach SQL użycie daty zamiast daty i godziny pozwala uniknąć konieczności radzenia sobie z godzinami. Skorzystaj z następującego przykładu: zadeklaruj noTime data = getdate (), withTime datetime = getdate () wybierz @ noTime, @ withTime
ozkary
1
obsada jako data jest świetna, jeśli potrzebujesz tylko daty. Jednak często potrzebna jest bieżąca data o północy, aby można było dokonać dalszych manipulacji datą. DATEraz 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 przypadkach DATEADD()podejście króluje.
Xedni,
To nie działa dla każdej daty. Błędnie 02182018DATEDIFFThe conversion of a datetime2 data type to a datetime data type resulted in an out-of-range datetime valueselect DATEDIFF(dd, 0, convert(datetime2(0), '0218-09-12', 120))
wpisałem
1
@ BernhardDöbler w lipcu 2009 roku, kiedy odpowiedziałem: „0218” byłaby prawidłową datą, więc nie dotarłbyś tak daleko. Również „0” nie jest konwertowane na 19000101 dla datetime2. Spróbuj tego wyboruSELECT DATEDIFF(dd, '19000101', convert(datetime2(0), '0218-09-12', 120))
gbn
69

W SQL Server 2008 możesz użyć:

CONVERT(DATE, getdate(), 101)
Anto Raja Prakash
źródło
13
Trzeci argument nie ma absolutnie żadnego wpływu na wynik przy konwersji z a datetimena date, więc twoje rozwiązanie sprowadza się do sprawiedliwego CONVERT(DATE,getdate()), co zostało już zasugerowane więcej niż raz.
Andriy M,
Wystarczy użyć CAST(GETDATE() AS DATE)lub ściśle ANSI, CAST(CURRENT_TIMESTAMP AS DATE)które moim zdaniem jest bezwartościowe. Zostań z pierwszym.
Ivanzinho,
52

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:

SELECT CONVERT(DATE,GETDATE())
Arjan Fraaij
źródło
21
SELECT CAST(FLOOR(CAST(getdate() AS FLOAT)) AS DATETIME)

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

Gary McGill
źródło
Zobacz odpowiedź GBN, wielu badało to. DATETIME NIE są przechowywane jako zmiennoprzecinkowe, dlatego użycie DATEADD / DATEDIFF pozwala uniknąć matematycznej manipulacji koniecznej do CAST pomiędzy typami.
MatBailie
Mogę zaakceptować fakt, że możesz chcieć uniknąć rzutowania z DATETIME na FLOAT z powodu, który opisujesz, ale w takim przypadku nie jest domyślną konwersją zera w opcji OP (a) również? Hmmm ... Przypuszczam, że w takim przypadku nie jest to PŁYWAK, a serwer jest prawdopodobnie wystarczająco inteligentny, aby odrzucić informacje o czasie. OK, przyznaję :-)
Gary McGill
0 jest rzeczywiście niejawną konwersją z typu liczbowego (zgaduję, że INT) na DATETIME. Ponieważ jest to ciągłe wyrażenie, optymalizator może to zrobić w czasie kompilacji Procedur składowanych i musi to zrobić tylko raz, aby dynamicznie wykonać SQL. Krótko mówiąc, jest to jednorazowy narzut, zapytanie oparte na FLOAT ma ekwiwalentny narzut dla każdego wiersza.
MatBailie
Rzucanie na pływaka jest strasznie nieprecyzyjne. Ta odpowiedź powinna zostać usunięta. Nikt nie powinien używać tego kodu.
usr
3
Nie wspominając już o tym, że rzutowanie na float i powrót do datetime nie jest bezpieczne - float nie ma wystarczającej precyzji. Dlatego myślę, że w ogóle nie można tego polecić. Zobacz ten post, aby uzyskać więcej szczegółów .
ErikE
17

W SQL Server 2008 istnieje typ danych DATE (także typ danych TIME).

CAST(GetDate() as DATE)

lub

declare @Dt as DATE = GetDate()
Metafora
źródło
Tego właśnie użyłem i działało dobrze. To chyba najprostsza odpowiedź. Jakieś wady związane z używaniem w połączeniu z / CONVERT?
joelmdev
1
CAST i CONVERT są równoważne pod względem funkcji. Różnica polega na tym, że CAST jest częścią standardu ANSI, podczas gdy CONVERT jest specyficzny dla T-SQL. Dlatego w miarę możliwości używaj CAST.
troy
@troy Używam CAST, ponieważ mogę zapisać 3 litery do pisania, a składnia jest jaśniejsza niż CONVERT, część ANSI Standard jest bezwartościowa
Ivanzinho
8

Oto kolejna odpowiedź z innego duplikatu pytania:

SELECT CAST(CAST(getutcdate() - 0.50000004 AS int) AS datetime) 

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:

DATEADD   MAGIC FLOAT
500       453
453       360
375       375
406       360

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.

Jeff Meatball Yang
źródło
1
To okropne. Nigdy nie naraziłbym swoich danych na takie ryzyko. Kto wie, czy jest to poprawne dla wszystkich okresów danych, nie tylko tych testowanych.
usr
@usr Och, to prawda, to tylko magiczna liczba i nie należy jej używać z tego powodu. Jeśli chcesz sprawdzić jego poprawność, po prostu umieść wszystkie możliwe daty jednego dnia w tabeli i sprawdź wyniki! Zobacz także ten post, aby uzyskać więcej informacji.
ErikE
@ErikE dobry punkt. Twoja odpowiedź daje jednak możliwość użycia, '12:00:00.003'która moim zdaniem jest znacznie lepsza.
usr
6
SELECT CAST(CAST(GETDATE() AS DATE) AS DATETIME)
Byju
źródło
4
Prawidłowa opcja, tak. Sugerowane więcej niż jeden raz w tym wątku.
Andriy M
Szczerze mówiąc, to rozwiązanie jest najłatwiejsze do odczytania. Moje goto
BelgoCanadian
5

Naprawdę lubię:

[date] = CONVERT(VARCHAR(10), GETDATE(), 120)

120Kod format będzie zmusić datę do standardu ISO 8601:

'YYYY-MM-DD' or '2017-01-09'

Bardzo łatwy w użyciu w dplyr ( R) i pandach ( Python)!

emehex
źródło
3

STRZEC SIĘ!

Metoda a) ib) NIE zawsze ma taki sam wynik!

select DATEADD(dd, DATEDIFF(dd, 0, '2013-12-31 23:59:59.999'), 0)

Wynik: 2014-01-01 00:00:00.000

select cast(convert(char(11), '2013-12-31 23:59:59.999', 113) as datetime)

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

broslaw
źródło
1
.999 nie można zapisać w SQL Server w DATETIMEkolumnie. 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.
Adam Wenger
Masz rację. Nie chciałem opublikować tego jako odpowiedzi na pytanie PO, ale jako komentarz do zobaczenia przez innych, ale miałem tylko 11 punktów reputacji i 15 jest potrzebne do komentowania.
broslav
W pierwszym fragmencie stała ciągu jest domyślnie konwertowana na datę i godzinę, w drugim pozostaje ciągiem (a 113 jest po prostu ignorowane).
Andriy M
2

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:

select date_only(dd)

Implementacja date_onlymoże być dowolna - teraz jest abstrakcyjna, a wywoływanie kodu jest znacznie czystsze.

Anton Gogolev
źródło
Kiedyś opracowałem wyzwalacz do czasu szorowania z wybranych kolumn. Jeśli dane nie mogą być złe, nie musisz ich czyścić.
Philip Kelley,
2
Metoda UDF ma wadę, nie są one SARGable. W przypadku użycia w klauzulach JOIN lub WHERE optymalizator nie może używać INDEKSÓW w celu poprawy wydajności. Zastosowanie metody DATEADD / DATEDIFF jest jednak SARGable i będzie mogło korzystać z INDEKSÓW. (Najwyraźniej metoda FLOAT jest również SARGable)
MatBailie,
1
@MatBailie Zaczynam się różnić! UDF zdecydowanie nie są SARGable, ale Dateadd nie jest też konwertowany do pływającego! WHERE DateAdd(DateDiff(Column)) = @DateValuenie użyje indeksu. Z drugiej strony WHERE Column >= dbo.UDF(@DateValue) AND Column < dbo.UDF(@DateValue + 1) jest SARGable. Uważaj więc, jak to ująłeś.
ErikE
2

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

Joel Coehoorn
źródło
Dzięki, pomyślałem, że o to wcześniej trzeba było zapytać. Dziwne jest jednak to, że moje eksperymenty wykazały, że metoda float jest wolniejsza o 3,5% na SQL Server 2008 niż metoda dateadd (dd, 0, datediff (dd, 0, getDate ())). Testy przeprowadzałem wiele razy dla każdej metody, a serwer bazy danych nie był wtedy używany do niczego innego.
Stephen Perelson
Powiedzmy, że sceptycznie podchodzę do testów porównawczych wykonanych przez każdego, kto nie wykazał, że wykonuje testy porównawcze regularnie i w bardzo naukowy sposób w ramach swojej pracy. Nawet benchmark Thomasa w linku gbn ma pewne oczywiste problemy, gdy na niego spojrzysz. To niekoniecznie czyni to błędnym, po prostu nie definitywnym. Metoda cast / floor / cast była od dawna akceptowaną najszybszą metodą i podejrzewam, że kiedyś była to bezsprzecznie prawda. To powiedziawszy, zaczynam to rozważać; szczególnie dla SQL Server 2008, gdzie i tak jest to zupełnie niepotrzebne.
Joel Coehoorn
1
Metoda łańcuchowa jest niezwykle łatwa w użyciu, czytaniu i zapamiętywaniu. Są to bardzo ważne czynniki, które moim zdaniem nie doceniasz!
Ben
1
@JoelCoehoorn, konwersja stylu 121 nazywa się „ODBC Canonical”. Nie zmienia się w zależności od sortowania ani ustawień regionalnych. Trick string jest również łatwy do uogólnienia na rok, rok + miesiąc, dzień, godzinę lub minutę.
Ben
1
@Ben Sztuczka strunowa uczy programistów używania konwersji ciągów. Oni pracują , ale data matematyka jest znacznie, znacznie lepszy, z wielu powodów, z których nie najmniej ważnym jest prędkość - ale jeszcze bardziej za to, co uczą się pracy z datami-as-numerów przyznaje dewelopera i jego umysłowych zdolności do być płynnym z manipulowaniem liczbami w kodzie.
ErikE
2

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

 CAST(
FLOOR( CAST( GETDATE() AS FLOAT ) )
AS DATETIME
)

drugi raz znalazłem to rozwiązanie ... złapałem ten kod

Carter Cole
źródło
1
Konwersja na float nie jest bezpieczna .
ErikE
2
CAST(round(cast(getdate()as real),0,1) AS datetime)

Ta metoda nie używa funkcji łańcuchowej. Datejest w zasadzie prawdziwym typem danych z cyframi po przecinku, które stanowią ułamek dnia.

myślę, że będzie to szybsze niż wiele.

Shantanu Singh Chauhan
źródło
1
Rzucanie jako float nie jest bezpieczne .
ErikE
2

Dla mnie poniższy kod jest zawsze zwycięzcą:

SELECT CONVERT(DATETIME, FLOOR(CONVERT(FLOAT,GETDATE())));
użytkownik1920017
źródło
1
Zasadniczo taki sam jak sugestia @Gary McGill .
Andriy M,
1
Rzucanie jako float nie jest bezpieczne .
ErikE
2

wybierz CONVERT (char (10), GetDate (), 126)

Diego
źródło
Jaka jest zasadnicza różnica twojej sugestii od metody wymienionej w odpowiedzi @ broslav lub od metody, która została określona jako najwolniejsza w tym wątku (ten sam link, co w zaakceptowanej odpowiedzi)?
Andriy M
1

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

create function dateonly (  @dt datetime )
returns datetime
as
begin
return cast(floor(cast(@dt as float))as int)
end
Aaron West
źródło
1

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.

Dr Drew
źródło
One nie są takie same. Inne odpowiedzi sugerowały rzutowanie go na datę bez komponentu czasu i pozostawienie go w ten sposób. Moje posty ustawiają go na datę i godzinę o północy. Jest duża różnica; spróbuj wyeksportować do MS Excel, a zobaczysz, że obsługuje on czas danych znacznie lepiej niż data.
Dr Drew
Pierwszy jest dokładnie taki sam.
Mikael Eriksson
Ok, tak, teraz to widzę. W razie potrzeby chętnie usunę moją odpowiedź jako duplikat.
Dr Drew
1

Myślę, że jeśli trzymasz się tego ściśle TSQL, jest to najszybszy sposób na skrócenie czasu:

 select convert(datetime,convert(int,convert(float,[Modified])))

Odkryłem, że ta metoda obcięcia jest o około 5% szybsza niż ta DateAddmetoda. Można to łatwo zmienić, aby zaokrąglić do najbliższego dnia w następujący sposób:

select convert(datetime,ROUND(convert(float,[Modified]),0))
Jamie G.
źródło
Konwersja na float nie jest bezpieczna .
ErikE
1

Tutaj utworzyłem funkcję usuwania niektórych części datetime dla SQL Server. Stosowanie:

  • Pierwszy parametr to data i godzina, która ma zostać usunięta.
  • Drugi parametr to znak:
    • s: zaokrągla do sekund; usuwa milisekundy
    • m: zaokrągla do minut; usuwa sekundy i milisekundy
    • h: zaokrągla do godzin; usuwa minuty, sekundy i milisekundy.
    • d: zaokrągla do dni; usuwa godziny, minuty, sekundy i milisekundy.
  • Zwraca nową datę / godzinę

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

Max Vargas
źródło
Dzięki, Andriy! Nie wiedziałem, że moja rekomendacja nie była tak skuteczna. Przynajmniej działa, ale masz rację.
Max Vargas
1

Na wypadek, gdyby ktoś szukał tutaj wersji Sybase, ponieważ kilka powyższych wersji nie działało

CAST(CONVERT(DATE,GETDATE(),103) AS DATETIME)
  • Testowane w I SQL v11 działającym na serwerze Adaptive Server 15.7
Alan
źródło
To lepiej pasuje jako edycja zaakceptowanej odpowiedzi. Z 20 innymi odpowiedziami zostanie to pochowane i prawie nieodnalezione. Również zaakceptowana odpowiedź wspomina o użyciu cast: W przypadku SQL Server 2008+ można dotychczas CAST. Lub po prostu użyj daty, więc nie ma czasu na usunięcie.
EWit
Najlepiej byłoby opublikować to jako odpowiedź na równoważne pytanie Sybase. Jeśli nie ma takiego pytania, możesz je utworzyć (i sam na nie odpowiedzieć).
Andriy M,
Poza tym nie ma sensu określać trzeciego parametru jako CONVERT podczas konwersji datetimena date: żaden z nich nie ma własnego formatu.
Andriy M
0

Jeśli to możliwe, do takich specjalnych rzeczy lubię korzystać z funkcji CLR.

W tym przypadku:

[Microsoft.SqlServer.Server.SqlFunction]
    public static SqlDateTime DateOnly(SqlDateTime input)
    {
        if (!input.IsNull)
        {
            SqlDateTime dt = new SqlDateTime(input.Value.Year, input.Value.Month, input.Value.Day, 0, 0, 0);

            return dt;
        }
        else
            return SqlDateTime.Null;
    }
tjeuten
źródło
0

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.

CraigTP
źródło
Korzystanie z UDF może być przydatne w niektórych sytuacjach (np. Podczas szorowania parametrów). Ale w większości sytuacji jest to okropne rozwiązanie - uruchomienie UDF raz dla każdego wiersza jest sposobem na zabicie wykonania zapytania bez potrzeby!
ErikE
@ErikE - nie zgadzam się, Erik, UDF są zabójcami wydajności, dlatego mówię, że jeśli możesz użyć SQL Server 2008 lub nowszego i użyć wbudowanego typu danych, który zrobi to za Ciebie, będzie to najlepsze rozwiązanie (zarówno pod względem osiągnięcia wymaganych wymagań, jak i wydajności). Jeśli utkniesz ze starszą wersją programu SQL Server, która nie obsługuje tego natywnie, poświęcisz coś , aby osiągnąć swoje wymagania.
CraigTP
Prawdziwe. Byłoby miło, gdyby silnik bazy danych dał nam coś, co było SARGable, ale łatwiej wyrazić. W międzyczasie, jeśli szukasz wartości, która znajduje się w dowolnym momencie w ciągu całego dnia, to jest nadal najlepszym rozwiązaniem (przynajmniej dla starszych wersjach SQL) 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.
ErikE
@ErikE - Nie martw się, Erik. Kiedy korzystałem z UDF, albo pracowałem z małymi zestawami danych, w których wydajność nie jest najważniejsza, lub, co bardziej prawdopodobne, filtrowałem zapytanie względem „surowego” pola daty (aby zapewnić możliwość sargowania), ale wybrałem kolumnę z zastosowanym UDF. Ponieważ po przefiltrowaniu są to zwykle małe zestawy danych, uruchamianie UDF na tak małej liczbie rekordów nie jest tak dużym spadkiem wydajności. To powiedziawszy, podnosicie bardzo dobry punkt i zaktualizowałem moją odpowiedź, aby to odzwierciedlić.
CraigTP
-4

Użyłbym:

CAST
(
CAST(YEAR(DATEFIELD) as varchar(4)) + '/' CAST(MM(DATEFIELD) as varchar(2)) + '/' CAST(DD(DATEFIELD) as varchar(2)) as datetime
) 

W ten sposób skutecznie tworzysz nowe pole z pola daty, które już masz.

Jabu
źródło
2
Dlaczego chcesz to zrobić? Czy uważasz, że wydobywanie bitów z datetimewartości, konwertowanie ich na ciągi, łączenie ich razem i wreszcie przekształcanie wyniku z powrotem datetimejest lepsze niż np. Wykonywanie bezpośrednich obliczeń na oryginale datetime( metoda DATEADD/ DATEDIFF)?
Andriy M,
Ponadto, jakie są MMi DD? W SQL Server nie ma takich funkcji.
Andriy M,