Eine interessante Sache über DATEDIFF()
Funktion in SQL Server besteht darin, dass Ihr SET DATEFIRST
ignoriert wird Wert.
Dies ist jedoch kein Fehler. Dokumentation von Microsoft für DATEDIFF()
heißt es eindeutig:
Angabe von SET DATEFIRST
hat keine Auswirkung auf DATEDIFF
. DATEDIFF
verwendet immer den Sonntag als ersten Tag der Woche, um sicherzustellen, dass die Funktion deterministisch arbeitet.
Falls Sie es nicht wissen, SET DATEFIRST
legt den ersten Tag der Woche für Ihre Sitzung fest. Es ist eine Zahl von 1 bis 7 (was Montag bis Sonntag entspricht).
Der Anfangswert für SET DATEFIRST
wird implizit durch die Spracheinstellung gesetzt (die Sie mit SET LANGUAGE
einstellen können Erklärung). Der tatsächliche Wert hängt von der eingestellten Sprache ab. Zum Beispiel der Standardwert für us_english
Sprache ist 7
(Sonntag), während die Standardeinstellung für British
Sprache ist 1
(Montag).
Sie können jedoch ein SET DATEFIRST
verwenden -Anweisung, um dies zu überschreiben, sodass Sie weiterhin dieselbe Sprache verwenden können, während Sie für den ersten Tag der Woche einen anderen Tag verwenden.
Aber wie gesagt, das SET DATEFIRST
Wert hat keine Auswirkung auf DATEDIFF()
Funktion. Das DATEDIFF()
Die Funktion geht immer davon aus, dass Sonntag der erste Tag der Woche ist, unabhängig von Ihrem SET DATEFIRST
Wert.
Dies kann einige interessante Probleme bei der Verwendung von DATEDIFF()
verursachen wenn Sie nicht wissen, wie es funktioniert.
Wenn Sie sich in dieser Situation befinden, können die Beispiele auf dieser Seite hoffentlich helfen.
Beispiel 1 – Das Problem
Hier ist zunächst ein Beispiel für das eigentliche Problem. Beachten Sie, dass wir SET DATEFIRST
abrufen können Wert, indem Sie @@DATEFIRST
auswählen .
DECLARE @startdate date ='2025-01-05', @enddate date ='2025-01-06';SET LANGUAGE us_english;SELECT @@DATEFIRST AS 'SET DATEFIRST Value', DATEDIFF(week, @startdate, @enddate) AS 'us_english DATEDIFF() Result';SET LANGUAGE British;SELECT @@DATEFIRST AS 'SET DATEFIRST Value', DATEDIFF(week, @startdate, @enddate) AS 'British DATEDIFF() Result';
Ergebnis:
+-----------------------+--------------------- ----------+| SET DATEFIRST Wert | us_english DATEDIFF() Ergebnis ||-----------------------+------------------- -------------|| 7 | 0 |+----------------------+------------------------------- --------++-----------------------+--------------- --------------+| SET DATEFIRST Wert | Britisch DATEDIFF() Ergebnis ||---------------------+------------------- ----------|| 1 | 0 |+----------------------+------------------------------- ------+
In diesem Fall fällt der erste Termin auf einen Sonntag und der zweite Termin auf einen Montag. Daher würden Sie normalerweise das britische DATEDIFF()
erwarten Ergebnis, um 1
zurückzugeben . Sie würden dies erwarten, weil die Wochenteilgrenze überschritten wird, wenn sie von Sonntag auf Montag geht (weil die SET DATEFIRST
Wert ist 1
was „Montag“ bedeutet, und Montag markiert den Beginn einer neuen Woche).
Aber weil DATEDIFF()
ignoriert Ihr SET DATEFIRST
-Wert und davon ausgeht, dass Sonntag der Wochenbeginn ist, erhalten wir das gleiche Ergebnis für beide Sprachen.
Nur um sicherzugehen, führe ich die Abfrage noch einmal aus, aber dieses Mal setze ich den SET DATEFIRST
Wert explizit . Mit anderen Worten, anstatt die Sprache festzulegen, verwende ich den SET DATEFIRST
Aussage:
DECLARE @startdate date ='2025-01-05', @enddate date ='2025-01-06';SET DATEFIRST 7;SELECT @@DATEFIRST AS 'SET DATEFIRST Value', DATEDIFF(week, @startdate, @enddate) AS 'us_english DATEDIFF() Result';SET DATEFIRST 1;SELECT @@DATEFIRST AS 'SET DATEFIRST Value', DATEDIFF(week, @startdate, @enddate) AS 'British DATEDIFF() Result';
Ergebnis:
+-----------------------+--------------------- ----------+| SET DATEFIRST Wert | us_english DATEDIFF() Ergebnis ||-----------------------+------------------- -------------|| 7 | 0 |+----------------------+------------------------------- --------++-----------------------+--------------- --------------+| SET DATEFIRST Wert | Britisch DATEDIFF() Ergebnis ||---------------------+------------------- ----------|| 1 | 0 |+----------------------+------------------------------- ------+
Dasselbe Ergebnis, auch wenn Sie explizit SET DATEFIRST
setzen Wert. Das ist jedoch keine Überraschung – ich wäre überrascht, wenn es nicht wäre das gleiche Ergebnis zurückgeben.
Außerdem bestätigt dies einfach, dass DATEDIFF()
funktioniert genau wie beabsichtigt.
Wie ändern wir es also, damit unser DATEDIFF()
Ergebnisse ehren unser SET DATEFIRST
Wert?
Die Lösung
Hier ist eine Lösung / Problemumgehung, mit der Sie die beabsichtigten Ergebnisse erzielen können. Dadurch wird sichergestellt, dass Ihr SET DATEFIRST
Einstellungen werden in Ihr DATEDIFF()
eingerechnet Ergebnisse.
Alles, was Sie tun müssen, ist @@DATEFIRST
zu subtrahieren aus den Eingabedaten.
DECLARE @startdate date ='2025-01-05', @enddate date ='2025-01-06';SET DATEFIRST 7;SELECT @@DATEFIRST AS 'SET DATEFIRST Value', DATEDIFF(week, DATEADD(day , [email protected]@DATEFIRST, @startdate), DATEADD(day, [email protected]@DATEFIRST, @enddate)) AS 'us_english DATEDIFF() Result';SET DATEFIRST 1;SELECT @@DATEFIRST AS 'SET DATEFIRST Value', DATEDIFF(week, DATEADD(day, [email protected]@DATEFIRST, @startdate), DATEADD(day, [email protected]@DATEFIRST, @enddate)) AS 'British DATEDIFF() Result';Ergebnis:
+-----------------------+--------------------- ----------+| SET DATEFIRST Wert | us_english DATEDIFF() Ergebnis ||-----------------------+------------------- -------------|| 7 | 0 |+----------------------+------------------------------- --------++-----------------------+--------------- --------------+| SET DATEFIRST Wert | Britisch DATEDIFF() Ergebnis ||---------------------+------------------- ----------|| 1 | 1 |+-----------------------+------------------------------- ------+Dies verwendet das
DATEADD()
Funktion, um die Eingabedaten um den Betrag von@@DATEFIRST
zu reduzieren (das ist IhrSET DATEFIRST
Wert).In diesem Fall das
DATEDIFF()
Die Funktion verwendet immer noch den Sonntag als ersten Tag der Woche, die tatsächlichen Daten, die in der Berechnung verwendet werden, sind jedoch unterschiedlich. Sie wurden um den Betrag von@@DATEFIRST
in der Zeit zurückversetzt .Das folgende Beispiel zeigt die Datumsangaben, die in der Berechnung verwendet wurden:
DECLARE @startdate date ='2025-01-05', @enddate date ='2025-01-06';SET DATEFIRST 7;SELECT @startdate AS 'Original Date', @@DATEFIRST AS 'Subtract By', DATEADD(day, [email protected]@DATEFIRST, @startdate) AS 'Resulting Date'UNION ALLSELECT @enddate, @@DATEFIRST, DATEADD(day, [email protected]@DATEFIRST, @enddate); SET DATEFIRST 1;SELECT @startdate AS 'Original Date', @@DATEFIRST AS 'Subtract By', DATEADD(day, [email protected]@DATEFIRST, @startdate) AS 'Ergebnisdatum'UNION ALLSELECT @enddate, @@DATEFIRST , DATEADD(day, [email protected]@DATEFIRST, @enddate);Ergebnis:
+------------+---------------+------------ ------+| Ursprüngliches Datum | Subtrahieren nach | Ergebnisdatum ||-----------------+---------------+------------ ------|| 05.01.2025 | 7 | 2024-12-29 || 06.01.2025 | 7 | 2024-12-30 |+----------------+---------------+--------- ---------++----------------+---------------+----- -------------+| Ursprüngliches Datum | Subtrahieren nach | Ergebnisdatum ||-----------------+---------------+------------ ------|| 05.01.2025 | 1 | 04.01.2025 || 06.01.2025 | 1 | 2025-01-05 |+----------------+---------------+--------- ---------+
In unserer Problemumgehung also DATEDIFF()
verwendet das „Ergebnisdatum“ in seinen Berechnungen.
Wenn Sie auf Probleme mit DATEDIFF()
gestoßen sind Ignorieren von SET DATEFIRST
, hoffentlich hat dieser Artikel geholfen.