Welche Methode bietet die beste Leistung beim Entfernen des Zeitanteils aus einem Datums- / Uhrzeitfeld in SQL Server?
a) select DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)
oder
b) select cast(convert(char(11), getdate(), 113) as datetime)
Die zweite Methode sendet in beiden Fällen einige weitere Bytes, dies ist jedoch möglicherweise nicht so wichtig wie die Geschwindigkeit der Konvertierung.
Beide scheinen auch sehr schnell zu sein, aber es kann einen Geschwindigkeitsunterschied geben, wenn es um Hunderttausende oder mehr Zeilen geht?
Ist es auch möglich, dass es noch bessere Methoden gibt, um den Zeitanteil einer Datums- / Uhrzeitangabe in SQL zu entfernen?
Antworten:
Streng genommen ist die Methode
a
am wenigsten ressourcenintensiv:Bewährt weniger CPU-intensiv bei gleicher Gesamtdauer eine Million Zeilen von jemandem mit viel zu viel Zeit: Die effizienteste Methode in SQL Server, um Datum von Datum + Uhrzeit abzurufen?
Ich habe anderswo einen ähnlichen Test mit ähnlichen Ergebnissen gesehen.
Ich bevorzuge DATEADD / DATEDIFF, weil:
Beispiel: Warum ist mein CASE-Ausdruck nicht deterministisch?
Bearbeiten, Okt 2011
Für SQL Server 2008+ können Sie CAST zu
date
dhCAST(getdate() AS date)
. Oder verwenden Sie einfach dendate
Datentyp, damit Sie keine Zeit zum Entfernen haben.Bearbeiten, Jan 2012
Ein Beispiel dafür, wie flexibel dies ist: Sie müssen nach gerundeten Zeit- oder Datumsangaben in SQL Server berechnen
Bearbeiten, Mai 2012
Verwenden Sie dies nicht in WHERE-Klauseln und dergleichen, ohne darüber nachzudenken: Das Hinzufügen einer Funktion oder eines CAST zu einer Spalte macht die Indexverwendung ungültig. Siehe Nummer 2 hier: http://www.simple-talk.com/sql/t-sql-programming/ten-common-sql-programming-mistakes/
Dies ist ein Beispiel für spätere SQL Server-Optimierungsversionen, die CAST bis heute korrekt verwalten, aber im Allgemeinen ist dies eine schlechte Idee ...
Bearbeiten, September 2018, für datetime2
quelle
DATE
Datenzeit ist in Bezug auf Dinge wie dateadd, dateiff und die Interaktion mit anderen Datums- / Zeitdatentypen unangenehm einschränkend. In diesen FällenDATEADD()
regiert der Ansatz König.0218
statt2018
als das Jahr eingegeben und derDATEDIFF
Teil Ihrer Aussage löst eine Ausnahme ausThe conversion of a datetime2 data type to a datetime data type resulted in an out-of-range datetime value
Versuchen Sie:select DATEDIFF(dd, 0, convert(datetime2(0), '0218-09-12', 120))
SELECT DATEDIFF(dd, '19000101', convert(datetime2(0), '0218-09-12', 120))
In SQL Server 2008 können Sie Folgendes verwenden:
quelle
datetime
nach a. Daher läuftdate
Ihre Lösung effektiv auf das hinausCONVERT(DATE,getdate())
, was bereits mehr als einmal vorgeschlagen wurde.CAST(GETDATE() AS DATE)
oder streng ANSI,CAST(CURRENT_TIMESTAMP AS DATE)
was ich für wertlos halte. Bleib beim ersten.Natürlich ist dies ein alter Thread, aber um ihn zu vervollständigen.
Ab SQL 2008 können Sie den Datentyp DATE verwenden, um Folgendes zu tun:
quelle
... ist laut den Kommentaren unten keine gute Lösung.
Ich würde diese Antwort löschen, aber ich werde sie hier als Gegenbeispiel belassen, da ich denke, dass die Erklärung der Kommentatoren, warum es keine gute Idee ist, immer noch nützlich ist.
quelle
In SQL Server 2008 gibt es einen DATE-Datentyp (auch einen TIME-Datentyp).
oder
quelle
Hier ist noch eine Antwort von einer anderen doppelten Frage:
Diese magische Zahlenmethode ist etwas schneller als die DATEADD-Methode. (Es sieht aus wie ~ 10%)
Die CPU-Zeit in mehreren Runden von einer Million Datensätzen:
Beachten Sie jedoch, dass diese Zahlen möglicherweise irrelevant sind, da sie bereits SEHR schnell sind. Ohne Rekordsätze von 100.000 oder mehr konnte ich nicht einmal die CPU-Zeit zum Lesen über Null bringen.
In Anbetracht der Tatsache, dass DateAdd für diesen Zweck gedacht und robuster ist, würde ich DateAdd verwenden.
quelle
'12:00:00.003'
die ich für viel besser halte.quelle
Ich mag wirklich:
Der
120
Formatcode zwingt das Datum in die Norm ISO 8601:Super einfach in dplyr (
R
) und pandas (Python
) zu verwenden!quelle
IN ACHT NEHMEN!
Methode a) und b) haben NICHT immer die gleiche Leistung!
Ausgabe:
2014-01-01 00:00:00.000
Ausgabe:
2013-12-31 00:00:00.000
(Getestet auf MS SQL Server 2005 und 2008 R2)
BEARBEITEN: Laut Adams Kommentar kann dies nicht passieren, wenn Sie den Datumswert aus der Tabelle lesen, aber es kann passieren, wenn Sie Ihren Datumswert als Literal angeben (Beispiel: als Parameter einer gespeicherten Prozedur, die über ADO.NET aufgerufen wird).
quelle
DATETIME
Spalte gespeichert werden . Der höchste verfügbare Wert ist .997. Von: msdn.microsoft.com/en-us/library/ms187819.aspx sehen Sie, dass die Werte gerundet sind, um den tausendsten Platz auf 0, 3 oder 7 zu haben. Das OP wird nicht angezeigt den Wert aus Ihrem Test in ihren Tabellen.Entfernen Sie zunächst die Zeit für Einfügungen / Aktualisierungen. Bei der On-the-Fly-Konvertierung kann eine benutzerdefinierte Funktion in Bezug auf die Wartbarkeit nichts übertreffen:
Die Implementierung von
date_only
kann beliebig sein - jetzt ist sie abstrahiert und das Aufrufen von Code ist viel sauberer.quelle
WHERE DateAdd(DateDiff(Column)) = @DateValue
wird keinen Index verwenden. Auf der anderen SeiteWHERE Column >= dbo.UDF(@DateValue) AND Column < dbo.UDF(@DateValue + 1)
ist SARGable. Sei also vorsichtig, wie du es ausdrückst.Siehe folgende Frage:
Wie kann ich eine Datums- / Uhrzeitangabe in SQL Server kürzen?
Verwenden Sie auf keinen Fall die Zeichenfolgenmethode . Das ist ungefähr das Schlimmste, was Sie tun können.
quelle
Bereits beantwortet, aber ich werde das auch rauswerfen ... das soll auch gut vorgeformt sein, aber es funktioniert, indem man die Dezimalstelle (die die Zeit speichert) vom Float wegwirft und nur den ganzen Teil (das ist das Datum) zurückgibt.
Das zweite Mal, als ich diese Lösung gefunden habe ... habe ich mir diesen Code geholt
quelle
Diese Methode verwendet keine Zeichenfolgenfunktion.
Date
ist im Grunde ein realer Datentyp mit Ziffern vor der Dezimalstelle, die Bruchteil eines Tages sind.Das wird wohl schneller als viel.
quelle
Für mich ist der folgende Code immer ein Gewinner:
quelle
Wählen Sie CONVERT (char (10), GetDate (), 126).
quelle
ich denke du meinst
cast(floor(cast(getdate()as float))as datetime)
real ist nur 32-Bit und könnte einige Informationen verlieren
Das ist am schnellsten
cast(cast(getdate()+x-0.5 as int)as datetime)
... obwohl nur etwa 10% schneller
(about 0.49 microseconds CPU vs. 0.58)
Dies wurde empfohlen und dauert in meinem Test gerade genauso lange:
DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)
In SQL 2008 ist die SQL-CLR-Funktion mit 1,35 Mikrosekunden gegenüber 6,5 Mikroschnitten etwa fünfmal schneller als die Verwendung einer SQL-Funktion, was auf einen viel geringeren Overhead für Funktionsaufrufe für eine SQL-CLR-Funktion im Vergleich zu einer einfachen SQL-UDF hinweist.
In SQL 2005 ist die SQL CLR-Funktion laut meinen Tests 16-mal schneller als diese langsame Funktion:
quelle
Wie wäre es
select cast(cast my_datetime_field as date) as datetime)
? Dies führt zu demselben Datum mit der Uhrzeit 00:00, vermeidet jedoch jegliche Konvertierung in Text und vermeidet auch explizite numerische Rundungen.quelle
Ich denke, wenn Sie sich strikt daran halten
TSQL
, ist dies der schnellste Weg, um die Zeit zu verkürzen:Ich fand diese Kürzungsmethode etwa 5% schneller als die
DateAdd
Methode. Und dies kann leicht so geändert werden, dass es auf den nächsten Tag rundet:quelle
Hier habe ich eine Funktion zum Entfernen einiger Teile einer Datums- / Uhrzeitangabe für SQL Server erstellt. Verwendungszweck:
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
quelle
Nur für den Fall, dass hier jemand nach einer Sybase-Version sucht, da einige der oben genannten Versionen nicht funktioniert haben
quelle
cast
: Für SQL Server 2008+ können Sie bisher CAST verwenden. Oder verwenden Sie einfach das Datum, damit Sie keine Zeit zum Entfernen haben.datetime
zudate
: keiner von dem hat ein inhärentes Format.Wenn möglich, verwende ich für spezielle Dinge wie diese gerne CLR-Funktionen.
In diesem Fall:
quelle
Ich persönlich verwende hierfür fast immer benutzerdefinierte Funktionen, wenn ich mich mit SQL Server 2005 (oder einer niedrigeren Version) befasse. Es sollte jedoch beachtet werden, dass die Verwendung von UDFs bestimmte Nachteile hat, insbesondere wenn sie auf WHERE-Klauseln angewendet werden (siehe unten und die Kommentare zu dieser Antwort für weitere Details). Bei Verwendung von SQL Server 2008 (oder höher) - siehe unten.
Tatsächlich füge ich für die meisten Datenbanken, die ich erstelle, diese UDFs gleich zu Beginn hinzu, da ich weiß, dass die Wahrscheinlichkeit, dass ich sie früher oder später benötige, bei 99% liegt.
Ich erstelle eine für "nur Datum" und "nur Zeit" (obwohl die "nur Datum" bei weitem die am häufigsten verwendete von beiden ist).
Hier sind einige Links zu verschiedenen datumsbezogenen UDFs:
Wichtige SQL Server-Funktionen für Datum, Uhrzeit und Datum / Uhrzeit Funktion " Nur Datum abrufen"
Dieser letzte Link zeigt nicht weniger als drei verschiedene Möglichkeiten, um das Datum nur als Teil eines Datums- / Uhrzeitfelds abzurufen, und nennt einige Vor- und Nachteile der einzelnen Ansätze.
Wenn Sie eine UDF verwenden, sollten Sie beachten, dass Sie versuchen sollten, die Verwendung der UDF als Teil einer WHERE-Klausel in einer Abfrage zu vermeiden, da dies die Leistung der Abfrage erheblich beeinträchtigt. Der Hauptgrund dafür ist, dass die Verwendung einer UDF in einer WHERE-Klausel diese Klausel als nicht sargable darstellt. Dies bedeutet, dass SQL Server keinen Index mehr mit dieser Klausel verwenden kann, um die Geschwindigkeit der Abfrageausführung zu verbessern. In Bezug auf meine eigene Verwendung von UDFs verwende ich häufig die Spalte "Rohdatum" in der WHERE-Klausel, wende die UDF jedoch auf die Spalte SELECTed an. Auf diese Weise wird die UDF nur auf die gefilterte Ergebnismenge und nicht auf jede Zeile der Tabelle als Teil des Filters angewendet.
Natürlich ist der absolute beste ist Ansatz für diesen SQL Server 2008 (oder höher) zu verwenden und Ihre abscheiden Daten und Zeiten , als der Motor SQL Server - Datenbank dann nativ wird die einzelnen Datums- und Zeitkomponenten bereitstellt, und kann effizient Abfrage dieser unabhängig ohne dass eine UDF oder ein anderer Mechanismus erforderlich ist, um entweder den Datums- oder den Uhrzeitteil aus einem zusammengesetzten Datums- / Uhrzeittyp zu extrahieren.
quelle
WHERE DateColumn >= {TimeTruncatingExpression}(@DateValue) AND DateColumn < {TimeTruncatingExpression}(@DateValue + 1)
. Ich hatte das Gefühl, dass ich etwas sagen musste, da Sie sagten "Ich verwende fast immer UDFs", was weder die Nachteile noch die Möglichkeit, eine Nur-Datum-Abfrage SARGable zu erstellen, erklärte.Ich würde ... benutzen:
So erstellen Sie effektiv ein neues Feld aus dem Datumsfeld, das Sie bereits haben.
quelle
datetime
Wert zu extrahieren , sie in Zeichenfolgen zu konvertieren, diese miteinander zu verketten und das Ergebnis schließlich wieder in zu konvertieren,datetime
als z. B. direkte Berechnungen für das Originaldatetime
(dieDATEADD
/DATEDIFF
-Methode) durchzuführen ?MM
undDD
? In SQL Server gibt es keine derartigen Funktionen.