Что касается «почему», DATEDIFF()
принимает 3 аргумента: datepart
(строковое представление определенной части даты), startdate
, enddate
(оба из которых должны быть преобразованы в объект даты-выхода).
0
- это, по сути, эпоха SQL, которая в данном случае 1/1/1900
.Таким образом, разница в месяцах между 0 и 3/1/2019
составляет (119 * 12) +2 (+2, потому что мы исключаем март, поскольку мы не рассчитываем полный месяц) = 1430 месяцев.
Затем мы пытаемся добавить 2 месяца к нашей стоимости.DATEADD()
принимает 3 аргумента: datepart
, number
, date
.Но, в этом примере, вы добавляете 1430 месяцев к любой дате, до которой конвертируется -2 (в этом случае, я думаю, это будет 30.12.1899 или за 2 дня до эпохи).Таким образом, 1430 месяцев после 30.12.1999 будут 30.02.2009, но в феврале в Феврале будет только 28 дней, поэтому он возвращается 28.02.2009.В високосный год он, вероятно, вернется 2/29/2019.
Чтобы получить @LastDayPrevMonth
и @SecLastDayPrevMonth
только с DATEDIFF()
и DATEADD()
, вам просто нужно немного изменить свои вычисления,
Первое, что вы хотите сделать, это найти первый день вашего данного месяца.Это можно сделать с помощью DATEADD(month,DATEDIFF(month,0,@CurrentDate),0)
.По сути, мы используем то же самое, что использовали выше, чтобы вычислить количество месяцев с начала эпохи, но затем мы добавляем эти месяцы назад к эпохе.
Теперь, когда мы знаем первый день данного месяца, все, что нам нужно сделать, это вычесть дни, чтобы получить день из предыдущего месяца.
Итак,
DECLARE @CurrentDate date = '2019-03-15' ; -- Changed it to something in the middle of the month.
DECLARE @FirstDayOfGivenMonth = DATEADD(month,DATEDIFF(month,0,@CurrentDate),0) ; -- 3/1/2019
DECLARE @LastDayOfPrevMonth date = DATEADD(day,-1,@FirstDayOfThisMonth) ; -- 2/28/2019
DECLARE @SecLastDayOfPrevMonth date = DATEADD(day, -2, @FirstDayOfThisMonth) ; -- 2/27/2019
SELECT @LastDayOfPrevMonth AS LDPM, @SecLastDayOfPrevMonth AS SLDPM ;
DECLARE @FourDaysLeftInPrevMonth date = DATEADD(day, -4, @FirstDayOfThisMonth) ; -- 2/25/2019
SELECT @FourDaysLeftInPrevMonth AS FourDaysLeftPrev ;
Конечно, начиная с SQL 2012, все это можно сделать гораздо проще с помощью функции EOM()
, чтобы добраться до последнего дня месяца.Но если бы вы могли использовать только две оригинальные функции из исходного вопроса, это был бы один из способов получить нужные значения.