2016-04-14 17 views
3

Von der DATEADD Dokumentation verwendet:DATEADD Problem, wenn negative Zahl wird mit MONAT Datumsteil

Wenn Datumsteil Monat und das Datum Monat hat mehr Tage als die Rendite Monat und das Datum Tag existiert nicht in der Rückkehr Monat, der letzte Tag des Rückkehrmonats zurückgegeben wird. Zum Beispiel hat September 30 Tage; daher geben die zwei folgenden Anweisungen zurück: 2006-09-30 00: 00: 00.000:

SELECT DATEADD (Monat, 1, '2006-08-30');

SELECT DATEADD (Monat, 1, '2006-08-31');

Der SQL Server weiß, dass der letzte Tag des 2016-03 ist 31 und der letzte Tag des 2016-04 ist 30:

SELECT DAY(EOMONTH('2016-03-01')) -- 31 
SELECT DAY(EOMONTH('2016-04-01')) -- 30 

Dann, warum die folgenden:

SELECT DATEADD(MONTH, -1, '2016-04-30') 

kehrt 2016-03-30 00:00:00.000 statt 2016-03-31 00:00:00.000 ?

Auch wenn ich folgendes:

SELECT DATEADD(MONTH, -1, '2016-03-31') 

es richtig 2016-02-29 00:00:00.000 zurückgibt.

+3

Antwort ist da in Ihrer Frage selbst :) –

+3

... "und der Datumstag existiert nicht im Rückgabemonat" ... - da der 30. Tag im März existiert, gibt er den 30. März korrekt zurück – pastacool

+0

Wenn die EOMONTH-Funktion nicht genug für Sie ist und Sie sich an einen DATEADD-Ansatz halten möchten, könnten Sie etwas wie SELECT DATEADD (MM, DATEDIFF (MM, -1, GETDATE()), 0) verwenden. 1 LastDayOfMonth' – pastacool

Antwort

0

einfacher Workflow für DATEADD Funktion

dh. für Tag - Addieren Sie den Tag (nächsten gültigen Tag) für die Woche - die Woche hinzufügen (nächste 7 Tage) für den Monat-Addieren Monat (nur nächsten Monat und füllen Sie weiter, wenn das Datum nicht gültig ist) für Jahr -it's hinzufügen Jahr

SELECT DATEADD(MONTH, -1, '2016-03-31')

output: 2016-02-29 00:00:00.000

in Ihrem Beispiel:

2016-03-31 - 2016.02.31 (subtrahieren 1 Monat), aber dies ist kein gültiges Datum ist, so Funktion versuchen, rückwärts zu bekommen füllen (in negtive) \ Vorwärtsdatum füllen (in positiv). so ist das nächste gültige Datum zurück 2016-02-29.

Fazit: Funktion wird verwendet füllen vorwärts und rückwärts füllen.

0

Es funktioniert nicht mit positiven Zahlen von 30 gehen -> 31 entweder zum Beispiel:

SELECT DATEADD(MONTH, 1, '2016-09-30') 

Yields 2016-10-30 00:00:00.000 statt 2016-10-31 00:00:00.000 von

Vermutlich ist dies, weil Sie nicht einen 31. Tag haben können ein Monat mit 30 Tagen, würde es das Datumsfeld überlaufen, aber Sie können einen 30. eines Monats in einem Monat mit 31 Tagen gut haben.

+1

es funktioniert genau so, wie die Dokumentation es beschreibt – pastacool

+0

Es funktioniert, Sie suchen nach einem Datum in einem Monat ab dem Startdatum Der Monat 2016-30-09 ist also 2016-10-30. DATEADD wurde nicht entwickelt, um Ihnen die Monatsendwerte zu geben. Wie es passiert ist die Berechnung des Monats ab jetzt für die Daten 20xx-08-30 und 20xx-08-31 ist das gleiche Datum 20xx-09-30. –

1

Wie andere Kommentare gesagt haben, wenn der Tag des Monats im vorherigen Monat existiert, wird DATEADD es verwenden, und nicht davon ausgehen, dass Sie "den letzten Tag des Monats" wollen.

Wenn Sie in der Tat die „Letzter Tag des Monats“ wollen, werden Sie ein bisschen mehr Logik klopfen wie:

DECLARE @date DATETIME = '30 April 2016' 
SELECT CASE WHEN DATEDIFF(MONTH, @date, DATEADD(DAY, 1, @date)) = 1 THEN  DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, @date), 0)) 
     ELSE DATEADD(MONTH, -1, @date) 
    END 

Das wird davon ausgehen, dass, wenn es der letzte Tag der Monat, möchten Sie den letzten Tag des Monats im Vormonat und nicht explizit die 28., 29. oder 30..