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?


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)

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)

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

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.


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

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.


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)

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


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


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.


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


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


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.


1
Rzucanie jako float nie jest bezpieczne .
ErikE


2

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


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

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.



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

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


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

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

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.


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.


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,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.