Ermittlung eines bestimmten Datums mit T-SQL

By Frank Kalis

Posted on Dez 5, 2007 von in SQL Server

Heute ist der 05.12.2007. Was muss ich nun machen, um den letzten Sonntag davor in T-SQL zu ermitteln?
Ein Blick in den Kalendar zeigt, daß als Ergebnis der 02.12.2007 herauskommen muss.

Die bisher einfachste und sicherste Methode, die ich gefunden habe, um diese Art von Fragestellungen zu lösen, bedient sich eines simplen Tricks:

Das Referenzdatum im SQL Server ist der 01.01.1900. Dieses Datum kann auch repräsentiert werden durch die Integerzahl 0:

SELECT CAST(0 AS DATETIME)

-----------------------
1900-01-01 00:00:00.000

(1 row(s) affected)

Dies ist insofern wichtig zu wissen, als das der Lösungsweg sich ebenfalls Integerarithmetik bedient. Wichtig ist ebenfalls, zu wissen, daß der 01.01.1900 ein Montag war:

SELECT DATENAME(DW, '19000101')

------------------------------
Monday

(1 row(s) affected)

Mit diesen beiden Informationen gewappnet, kann man sich leicht ausrechnen, daß der "erste" Sonntag laut SQL Servers Rechnung nach dem Referenzdatum der 07.01.1900 gewesen ist:

SELECT DATENAME(DW, '19000107')

------------------------------
Sunday

(1 row(s) affected)

Darauf baut dieser Algorithmus auf:

SELECT DATEADD(DAY, DATEDIFF(DAY, '19000107', GETDATE()) / 7 * 7, '19000107')

-----------------------
2007-12-02 00:00:00.000

(1 row(s) affected)

Wie funktioniert der nun? Es ist hilfreich, zunächst einmal den Algorithmus zu zerlegen in seine Bestandteile:

SELECT DATEDIFF(DAY, '19000107', GETDATE()) 

-----------
39413

(1 row(s) affected)

liefert den Anzahl an Tagen zwischen dem 07.01.1900 und Heute.

SELECT DATEDIFF(DAY, '19000107', GETDATE()) / 7 * 7

-----------
39410

(1 row(s) affected)

liefert adjustiert nun diese Anzahl an Tagen auf ein "glattes" Ergebnis ohne Rest. Anders ausgedrückt haben wir zu diesem Zeitpunkt die Anzahl der vollen Wochen (ausgedrückt in Tagen) seit dem 07.01.1900. Diese Anzahl müssen wir nun nur noch auf den ersten Sonntag addieren, um den letzten Sonntag <= dem heutigen Datum zu erhalten und schlußendlich das Ergebnis zurück in ein gültiges Datum umwandeln. Dies geschieht mit Hilfe der DATEADD Funktion:

SELECT DATEADD(DAY, DATEDIFF(DAY, '19000107', GETDATE()) / 7 * 7, '19000107')

-----------------------
2007-12-02 00:00:00.000

(1 row(s) affected)

q.e.d.

Dieser Algorithmus hat gleich mehrere angenehme Nebeneffekte:

1. Der Zeitanteil, der durch GETDATE() eingeführt wird, wird direkt durch DATEDIFF eliminiert, was dazu führt, daß man in Abfragen unerwünschte Nebeneffekte ausschliesst.

2. Er ist unabhängig von irgendwelchen Computer-Einstellungen. Sprich, die DATEFIRST Einstellung, oder andere beeinflussen nicht das Ergebnis.

3. Er ist leicht und generisch adaptierbar für den Fall, daß man eventuell den vorletzten (oder nächsten) Sonntag braucht.

Beispiel 1: Gewünscht ist der nächste Sonntag (09.12.2007):

DECLARE @i int
SET @i = 1
SELECT DATEADD(DAY, DATEDIFF(DAY, '19000107', GETDATE()) / 7 * 7 + (7 * @i), '19000107')

-----------------------
2007-12-09 00:00:00.000

(1 row(s) affected)

Beispiel 2: Gewünscht ist der vorletzte Sonntag (25.11.2007):

DECLARE @i int
SET @i = -1
SELECT DATEADD(DAY, DATEDIFF(DAY, '19000107', GETDATE()) / 7 * 7 + (7 * @i), '19000107')

-----------------------
2007-11-25 00:00:00.000

(1 row(s) affected)

4. Er funktioniert auch mit jedem anderen Wochentag. Dazu muss man nur das Referenzdatum variieren.

Beispiel 1: Gewünscht ist der letzte Dienstag (04.12.2007):

DECLARE @i int
SET @i = 0
SELECT DATEADD(DAY, DATEDIFF(DAY, '19000102', GETDATE()) / 7 * 7 + (7 * @i), '19000102')

-----------------------
2007-12-04 00:00:00.000

(1 row(s) affected)

Beispiel 2: Gewünscht ist der nächste Freitag (07.12.2007):

DECLARE @i int
SET @i = 1
SELECT DATEADD(DAY, DATEDIFF(DAY, '19000105', GETDATE()) / 7 * 7 + (7 * @i), '19000105')

-----------------------
2007-12-07 00:00:00.000

(1 row(s) affected)

Für weitere Informationen stehen in der Rubrik  Datum und Zeit weitere Beiträge bereit.

Dieser Eintrag wurde eingetragen von und ist abgelegt unter SQL Server. Tags: , ,

Noch kein Feedback


Formular wird geladen...