Konvertieren Sie SQL Server Datetime-Felder Datumsteile vergleichen nur mit indexierten Lookups

stimmen
28

Ich habe ein tun convert(varchar,datefield,112)auf jedes Datumsfeld , das ich verwende in ‚zwischen‘ Abfragen in SQL Server , um sicherzustellen , dass ich für Termine nur bin Buchhaltung und fehlte nicht auf der Grundlage der Zeit Teil der Datetime - Felder.

Nun, ich höre, dass die Bekehrten nicht Wende sind und dass es bessere Methoden, in SQL Server 2005, das Datum Teil Datetimes in einer Abfrage zu vergleichen, um zu bestimmen, ob Daten in einer Reihe fallen.

Was ist die optimale, Wende, Methode der so etwas wie dies zu tun:

select * from appointments
where appointmentDate>='08-01-2008' and appointmentDate<'08-15-2008'
Veröffentlicht am 09/12/2008 um 15:59
quelle vom benutzer
In anderen Sprachen...                            


5 antworten

stimmen
65

Der beste Weg, den Zeitabschnitt eines Datum-Feld abzustreifen und wird unter Verwendung von datediff dateadd Funktionen.

   DateAdd(day, datediff(day,0, MydateValue), 0)

Dies geschieht AdvantEdge der Tatsache , dass SQL Server speichert als zwei ganzen Zahlen geht, man die Anzahl der Tage seit dem Tag entspricht „0“ - (1. Januar 1900), und die zweite , die die Anzahl von repräsentiert Zecken (jede Zecke ist etwa 3,33 ms seit Mitternacht) (für die Zeit) *.

Die obige Formel muss einfach nur die erste Ganzzahl gelesen. Es gibt keine Umwandlung oder Verarbeitung erforderlich ist, so ist es extrem schnell.

Um Ihre Fragen verwenden, um einen Index zu machen ... Mit dieser Formel auf dem Eingangsfilterparameter ersten oder auf der „anderen“ Seite des Gleichheitszeichens aus dem Tabelle Datum Zeitfeld, so dass der Abfrageoptimierer die Berechnung nicht ausgeführt hat auf jedem Datetime-Feld in der Tabelle, um zu bestimmen, welche Zeilen das Filterprädikat erfüllen. Das macht Ihr Suchargument "SARG-able" (Search argument)

Where MyDateTimeColumn > DateAdd(day, 
      datediff(day,0, @MydateParameter), 0)    -- SARG-able

eher, als

Where DateAdd(day, datediff(day,0, 
      MyDateTimeColumn ), 0) > @MydateParameter -- Not SARG-able

* HINWEIS. Intern wird die zweite ganze Zahl ist (die Zeitrang) speichert Zecken. In einem Tag sind 24 x 60 x 60 x 300 = 25.920.000 Ticks (serendipitously knapp unter dem Maximalwert eine 32-Bit-Ganzzahl halten kann). Allerdings brauchen Sie nicht zu kümmern, wenn arithmetisch ein Datetime Ändern ... Wenn Addieren oder Subtrahieren von Werten von Datetimes können Sie den Wert als Bruch zu behandeln, als wäre es genau gleich den Bruchteil eines Tages war, als ob die vollständige Datumzeit-Wert war eine Gleitkommazahl aus einem ganzzahligen Teil, der aus den Zeitpunkt darstellt, und den Bruchteil der Zeit darstellt). dh

`Declare @Dt DateTime  Set @Dt = getdate()  
 Set @Dt = @Dt + 1.0/24  -- Adds one hour  
 Select @Dt  
 Set @Dt = @Dt - .25 -- Moves back 6 hours  
 Select @Dt`
Beantwortet am 09/12/2008 um 16:07
quelle vom benutzer

stimmen
5

Konvertieren von numerischen Typen String-Werte (eine Art von Box) ist nicht die beste Ergebnis erzielt Methode zu tun, was Sie suchen. Es ist nicht wirklich über Index-Lage, da der tatsächliche Spaltentyp Datum Zeit ist.

Wenn Sie für die beste Art und Weise Abfrage nach Daten suchen, dann Ihr Beispiel ist richtig, aber Sie können die 3 ms Genauigkeit Unterschied in MSSQL berücksichtigen wollen. Es kann bedeuten, dass Aufzeichnungen von einem Tag können in einem anderen Tag des Ergebnis angezeigt.

Dies

select * from appointments where appointmentDate>='08-01-2008' and appointmentDate<'08-15-2008'

Sollte dies

select * from appointments where appointmentDate>='08-01-2008' and appointmentDate<='08-14-2008 23:59:59.996'
Beantwortet am 09/12/2008 um 16:11
quelle vom benutzer

stimmen
2

Es ist richtig - die Umwandlung abgefragt für jede Zeile wird ausgeführt, um die Umwandlung zu tun. Es ist besser, die Datumsspalten als Termine zu verlassen, und übergeben Sie Ihre where-Klauseln als Termine:

select * from appointments where appointmentdate between 
'08/01/2008' AND '08/16/2008'

Hinweis: Beim Verlassen der Zeit bedeutet Mitternacht ab (00: 00.000), so dass Sie alle Zeiten für 08/01 enthalten, und alle Zeiten von 08/15, und alles, was genau ist 2008.08.16 00.00.00

Beantwortet am 09/12/2008 um 16:06
quelle vom benutzer

stimmen
1

Haben eine berechnete beharrte Spalte den Ausdruck berechnen Sie benötigen. Wenn Spalten berechnet werden und beharren, können sie auch indiziert werden.

Beantwortet am 09/12/2008 um 16:10
quelle vom benutzer

stimmen
0

Es besteht auch die Möglichkeit , bei beschrieben http://www.stillnetstudios.com/comparing-dates-without-times-in-sql-server/

SELECT CAST(FLOOR(CAST( getdate() AS float )) AS datetime)
Beantwortet am 28/09/2011 um 13:31
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more