Could you hire me? Contact me if you like what I’ve done in this article and think I can create value for your company with my skills.

May 3, 2007 / by Zsolt Soczó

Dátum levágása TSQL-ben

Egyik MSHU-s jóakaróm jóvoltából megkaptam a teljes Inside TSQL 2005 sorozatot, és még jó pár egyéb könyvet is.
Az első részen, a Storage Engine részen már túlvagyok, sok érdekes dolgot olvastam benne, amelyeket majd egyik kevésbé rohanós pillanatomban összeszedek címszavakban.
Csak egyet emelnék ki. 2005-ben NEM a tranzakciós logból állítják elő a triggerek számára az inserted és deleted táblákat, hanem a snapshot isolationhöz kidolgozott row versioning eljárással. Na, ez pl. nekem új volt.

No, amit viszont most szeretnék bemutatni a TSQL Programing c. második kötetből, hogy egy időpontot is tartalmazó dátumról hogyan lehet hatékonyan levágni az idő részt (ha már egyszer nincs rendes date és time típus):

dateadd(d, 0, datediff(d, 0, getdate()))

Ügyes, ezt még nem láttam.

Én ezt ismertem, ez is benne van a könyvben:

cast(convert(varchar(8), getdate(), 112) as datetime)

Ezzel viszont már szívtam, mert itt ugye arra bazírozunk, hogy levágódik az idő rész a varchar hossza miatt, ez viszont egyes esetekben kiborítja a szervert. Asszem indexelt, számított oszlopban akartam ezt használni, de nem engedte, a túlcsordulás miatt. Mellesleg az első verzió szerintem sokkal gyorsabb.

Nem álltam meg, megmértem őket:

[source:SQL]
declare @i int, @e int
set @i = 0
set @e = 1000000

declare @start datetime
declare @end datetime
declare @d datetime

set @start = getdate()
while(@i < @e) begin --set @d = dateadd(d, 0, datediff(d, 0, getdate())) set @d = cast(convert(varchar(8), getdate(), 112) as datetime) set @i = @i + 1 end set @end = getdate() select datediff(ms, @start, @end) [/source] Az első verzió nálam kb. 1300 ms alatt fut le, a második 2000 körül. Nem óriási a különbség, de a stringes megoldás hibás viselkedése miatt most már inkább az elsőt preferálom. Van jobb megoldás esetleg?

Could you hire me? Contact me if you like what I’ve done in this article and think I can create value for your company with my skills.

LEAVE A COMMENT

5 COMMENTS

  • Szőke László September 1, 2007

    Mondjuk én nem értem a varchar(8)-at!
    Miért varchar és miért 8?

    Én ezt használom már 7 éve, és nem volt még gondom vele (igaz, hogy indexelt, számított oszlopban még nem próbáltam):

    select convert(datetime, convert(char(10), getdate(), 102))

    A mérési eredményed alapján gondolom, hogy ez is hasonlóan teljesít, mint amit kidobtál! Vagy lehet, hogy annál egy kicsit jobban, talán a char miatt?

    Megmérnéd?

  • Szőke László September 8, 2007

    Ne mérd meg vazze, de azért kíváncsi lennék arra amit kérdeztem!

  • Soczó Zsolt September 9, 2007

    Szőke Úr,
    mostanában nem ez volt a legfontosabb, hogy méricskéljek:

    http://soci.hu/blog/index.php/2007/09/09/megjottunk-soczo-panni-kamilla-es-soczo-benedek-gergo/

    Amúgy meg ott a kód, amivel mértem, csak le kell futtatnod.

  • Szőke László September 10, 2007

    Tényleg ott a kód, bocs!

    És a két kérdésem?

    Kezdem fordított sorrendbe:
    2.)
    Azt nem értem igazán, hogy miért használt valaki 8-at 10 helyett? Miért 20070910-re konvertál valaki, ha lehet konvertálni 2007.09.10-re is vagy 2007-09-10-re, stb?

    Miért jó stresszelni a szervert azzal, hogy na vazze, találd ki, hogy mire gondoltam!

    A 2007-09-10 azért jobb, mert ha az év van elöl, akkor a 2. a hónap, a 3. meg a nap. Nem tudok olyanról, hogy valahol a világon használnak ilyen sorrendet: ÉÉÉÉ.NN.HH.

    1.)
    Ha fix, hogy fix a hossz, akkor miért jó varchart használni char helyett?

    Tovább tart begépelni, ha már más szempont nem is számít!

    TOVÁBBÁ
    Ha már a teljesítmény ennyire központi téma nálad, akkor miért használsz SET-et lokális változók beállogatására?

    Ha egy helyen csak egyetlen változót kell beállítanod, akkor megértem, mert rövidebb begépelni mint a select-et.

    De! Miért használsz SET-et, ha egy helyen több értékadást is el kell végezned?

    set @a = 1
    set @b = 2

    helyett inkább:

    select @a = 1, @b = 2

    Mérhető a különbség!

    ÉS EGY KIS RÁADÁS:
    Miért jó a kód elején belőni két változót, amit 1 kilométerrel odébb használsz.

    Inkább így:
    select @i = 0, @e = 2000000;
    while (@i

  • Szőke László September 10, 2007

    Bő lé…

    Inkább így:
    select @i = 0, @e = 2000000;
    while (@i