it-swarm.com.de

Bester Ansatz zum Entfernen eines zeitlichen Teils von datetime in SQL Server

Welche Methode bietet die beste Leistung beim Entfernen des Zeitabschnitts aus einem datetime-Feld 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 ein paar weitere Bytes, aber das ist möglicherweise nicht so wichtig wie die Geschwindigkeit der Konvertierung.

Beide scheinen auch sehr schnell zu sein, aber es kann einen Unterschied in der Geschwindigkeit 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- und Uhrzeitangabe in SQL zu beseitigen?

492

Streng genommen ist die Methode a die ressourcenschonendste:

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

Bewährte weniger CPU-intensiv für die gleiche Gesamtdauer eine Million Zeilen von jemandem mit viel zu viel Zeit zur Verfügung: Effizienteste Methode in SQL Server, um Datum von Datum + Uhrzeit zu erhalten?

Ich habe einen ähnlichen Test auch an anderer Stelle mit ähnlichen Ergebnissen gesehen.

Ich bevorzuge das DATEADD/DATEDIFF, weil:

Bearbeiten, Okt 2011

Für SQL Server 2008+ können Sie CAST auf date setzen. Oder verwenden Sie einfach date, damit Sie keine Zeit zum Entfernen haben.

Bearbeiten, Januar 2012

Ein gelungenes Beispiel dafür, wie flexibel dies ist: Berechnung nach gerundeter Zeit- oder Datumsangabe in SQL Server erforderlich

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/

Nun, dies ist ein Beispiel für spätere Versionen des SQL Server-Optimierers, die CAST korrekt verwalten, aber im Allgemeinen wird es eine schlechte Idee sein ...

Bearbeiten, September 2018, für DatumZeit2

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

In SQL Server 2008 können Sie Folgendes verwenden:

CONVERT(DATE, getdate(), 101)
59

Natürlich ist dies ein alter Thread, aber um ihn zu vervollständigen.

Ab SQL 2008 können Sie den Datentyp DATE verwenden, um einfach Folgendes zu tun:

SELECT CONVERT(DATE,GETDATE())
44
Arjan Fraaij
SELECT CAST(FLOOR(CAST(getdate() AS FLOAT)) AS DATETIME)

... ist nicht eine gute Lösung, laut den Kommentaren unten.

Ich würde diese Antwort löschen, aber ich werde sie hier als Gegenbeispiel belassen, da ich die Erklärung der Kommentatoren für halte, warum keine gute Idee ist ist immer noch nützlich.

21
Gary McGill

In SQL Server 2008 gibt es einen DATE-Datentyp (auch einen TIME-Datentyp).

CAST(GetDate() as DATE)

oder

declare @Dt as DATE = GetDate()
15
Metaphor

Hier ist noch eine andere Antwort von einer anderen doppelte Frage:

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

Diese magische Zahlenmethode ist etwas schneller als die DATEADD-Methode. (Es sieht aus wie ~ 10%)

Die CPU-Zeit bei mehreren Runden mit einer Million Datensätzen:

DATEADD   MAGIC FLOAT
500       453
453       360
375       375
406       360

Beachten Sie jedoch, dass diese Zahlen möglicherweise irrelevant sind, da sie bereits SEHR schnell sind. Ohne 100.000 oder mehr Datensätze 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.

8
SELECT CAST(CAST(GETDATE() AS DATE) AS DATETIME)
5
Byju

Ich mag wirklich:

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

Der 120 -Formatcode zwingt das Datum in den ISO 8601-Standard:

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

Super einfach in dplyr (R) und pandas (Python) zu verwenden!

4
emehex

IN ACHT NEHMEN!

Methode a) und b) haben NICHT immer die gleiche Ausgabe!

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

Ausgabe: 2014-01-01 00:00:00.000

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

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. Dies kann jedoch passieren, wenn Sie Ihren Datumswert als Literal angeben (Beispiel: als Parameter einer gespeicherten Prozedur, die über ADO.NET aufgerufen wird).

3
broslav
CAST(round(cast(getdate()as real),0,1) AS datetime)

Diese Methode verwendet keine Zeichenfolgenfunktion. Date ist im Grunde ein realer Datentyp mit Nachkommastellen, die einen Bruchteil eines Tages darstellen.

das wird wohl schneller als viel.

Siehe diese Frage:
Wie kann ich eine Datums-/Uhrzeitangabe in SQL Server kürzen?

Was auch immer Sie tun, verwenden Sie nicht die String-Methode . Das ist ungefähr das Schlimmste, was Sie tun können.

2
Joel Coehoorn

wähle CONVERT (char (10), GetDate (), 126)

2
Diego

Strip-Zeit bei Einfügungen/Updates an erster Stelle. Bei der fliegenden Konvertierung kann nichts eine benutzerdefinierte Funktion hinsichtlich der Wartbarkeit übertreffen:

select date_only(dd)

Die Implementierung von date_only kann beliebig sein - jetzt ist sie abstrahiert und das Aufrufen von Code ist viel sauberer.

2
Anton Gogolev

Bereits beantwortet, aber ich werfe das hier auch raus ... dies funktioniert angeblich auch gut, aber es funktioniert, indem die Dezimalstelle (die die Zeit speichert) vom Float weggeworfen wird und nur der ganze Teil (der das Datum ist) zurückgegeben wird.

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

zum zweiten mal habe ich diese lösung gefunden ... ich habe diesen code abgeschnappt

2
Carter Cole

Für mich ist der folgende Code immer ein Gewinner:

SELECT CONVERT(DATETIME, FLOOR(CONVERT(FLOAT,GETDATE())));
2
user1920017

Hier habe ich eine Funktion erstellt, um einige Teile einer Datums- und Uhrzeitangabe für SQL Server zu entfernen. Verwendungszweck:

  • Der erste Parameter ist die zu entfernende Datumszeit.
  • Zweiter Parameter ist ein Zeichen:
    • s: rundet auf Sekunden; Entfernt Millisekunden
    • m: Runden zu Minuten; Entfernt Sekunden und Millisekunden
    • h: Runden zu Stunden; Entfernt Minuten, Sekunden und Millisekunden.
    • d: Runden zu Tagen; Entfernt Stunden, Minuten, Sekunden und Millisekunden.
  • Gibt die neue Datumszeit zurück

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

1
Max Vargas

Ich denke du meinst cast(floor(cast(getdate()as float))as datetime)

real ist nur 32-Bit und kann einige Informationen verlieren

Dies ist das schnellste cast(cast(getdate()+x-0.5 as int)as datetime)

... obwohl nur ca. 10% schneller(about 0.49 microseconds CPU vs. 0.58)

Dies wurde empfohlen und dauert in meinem Test gerade dieselbe Zeit: DATEADD(dd, DATEDIFF(dd, 0, getdate()), 0)

In SQL 2008 ist die SQL-CLR-Funktion mit 1,35 Mikrosekunden im Vergleich zu 6,5 Mikroschnitten etwa fünfmal schneller als die Verwendung einer SQL-CLR-Funktion, was auf einen viel geringeren Funktionsaufrufaufwand für eine SQL-CLR-Funktion im Vergleich zu einer einfachen SQL-UDF hinweist.

In SQL 2005 ist die SQL CLR-Funktion nach meinen Tests 16-mal schneller als diese langsame Funktion:

create function dateonly (  @dt datetime )
returns datetime
as
begin
return cast(floor(cast(@dt as float))as int)
end
1
Aaron West

Nur für den Fall, dass jemand hier nach einer Sybase-Version sucht, da einige der oben genannten Versionen nicht funktioniert haben

CAST(CONVERT(DATE,GETDATE(),103) AS DATETIME)
  • Getestet in I SQL v11 unter Adaptive Server 15.7
1
Alan

Wie wäre es mit select cast(cast my_datetime_field as date) as datetime)? Dies führt zu demselben Datum, wobei die Uhrzeit auf 00:00 eingestellt ist, vermeidet jedoch jegliche Konvertierung in Text und auch jegliche explizite numerische Rundung.

1
Dr. Drew

Ich denke, wenn Sie sich strikt an TSQL halten, ist dies der schnellste Weg, die Zeit zu verkürzen:

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

Ich fand diese Kürzungsmethode etwa 5% schneller als die DateAdd -Methode. Und dies kann leicht geändert werden, um auf den nächsten Tag zu runden:

select convert(datetime,ROUND(convert(float,[Modified]),0))
1
Jamie G

Wenn möglich, verwende ich für solche speziellen Dinge gerne CLR-Funktionen.

In diesem Fall:

[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
tjeuten

Ich persönlich verwende 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 angewendet werden zu den WHERE-Klauseln (siehe unten und die Kommentare zu dieser Antwort für weitere Details). Wenn Sie SQL Server 2008 (oder höher) verwenden - 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 ich sie mit einer Wahrscheinlichkeit von 99% früher oder später benötige.

Ich erstelle eines für "nur Datum" und "nur Uhrzeit" (obwohl das "nur Datum" bei weitem das am häufigsten verwendete ist).

Hier sind einige Links zu verschiedenen datumsbezogenen UDFs:

Grundlegende SQL Server-Funktionen für Datum, Uhrzeit und Datum/Uhrzeit
Get Date Only Function

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 versuchen, die UDF nicht als Teil einer WHERE-Klausel in einer Abfrage zu verwenden, 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 einen Index mit dieser Klausel nicht mehr verwenden kann, um die Geschwindigkeit von zu verbessern Abfrageausführung. In Bezug auf meine eigene Verwendung von UDFs verwende ich häufig die "raw" -Datumsspalte in der WHERE-Klausel, wende die UDF jedoch auf die SELECTed-Spalte an. Auf diese Weise wird die UDF nur auf die gefilterte Ergebnismenge angewendet und nicht auf jede Zeile der Tabelle als Teil des Filters.

Natürlich ist der absolut beste Ansatz, SQL Server 2008 (oder höher) zu verwenden und Datum und Uhrzeit zu trennen =, da das SQL Server-Datenbankmodul dann die einzelnen Datums- und Zeitkomponenten nativ bereitstellt und diese unabhängig voneinander effizient abfragen kann, ohne dass eine UDF oder ein anderer Mechanismus zum Extrahieren des Datums- oder Zeitteils aus einem zusammengesetzten Datetime-Typ erforderlich ist.

0
CraigTP