SQL Север - странное поведение DateDiff - PullRequest
0 голосов
/ 13 марта 2020

У меня следующий простой запрос

select DATEADD(MONTH, DATEDIFF(MONTH, -32, '2020-02-29')-32, -1)
select DATEADD(MONTH, DATEDIFF(MONTH, -31, '2020-02-29')-31, -1)

Я ожидаю, что выходные данные для каждой строки будут разными из-за разного количества месяцев в -31 и -32.

Оба эти строки возвращают 2017-07-31 00: 00: 00.000, и я понятия не имею, почему!

Может кто-нибудь объяснить мне это?

Ответы [ 2 ]

1 голос
/ 13 марта 2020

Из моего комментария:

Зачем вам другие значения? И DATEDIFF(MONTH, -32, '20200229')-32, и DATEDIFF(MONTH, -31, '20200229')-31 приводят к значению 1411. «Дата» -1 равна 1899-12-31, и добавление 1411 месяцев (117 лет 7 месяцев) к этому равно 2017-07-31.

Давайте разберем это:

SELECT DATEDIFF(MONTH, -32, '20200229')-32 AS DD1, DATEDIFF(MONTH, -31, '20200229')-31 AS DD2;

Это возвращает следующее:

DD1         DD2
----------- -----------
1411        1411

Мы можем разбить вышесказанное и на дальнейшие шаги. Для datetime дата 0 равна 1900-01-01, и каждое полное целое число представляет добавление такого количества дней к этой дате. Следовательно, -32 как дата - 1899-11-30, а -31 - 1899-12-01. Это дает нам два приведенных ниже выражения:

SELECT DATEDIFF(MONTH, '18991130', '20200229') AS M1, DATEDIFF(MONTH, '18991201', '20200229') AS M2;

Это возвращает следующее:

M1          M2
----------- -----------
1443        1442

Это имеет смысл, так как DATEDIFF считает количество "тиков" между 2 датами. Таким образом, для выражения DATEDIFF(YEAR, '2019-12-31T23:59:59.9999999','2020-01-01T00:00:00.000000') возвращается значение 1, хотя прошла только 1 миллисекунда, поскольку значение года изменилось (на 1).

Следующая часть этого выражения 1443 - 32 и 1442 - 31 соответственно. Это 1411 для обоих (по основам c по математике).

Тогда у вас есть "дата" -1. Затем вы добавляете 1411 месяцев (что составляет 117 лет и 7 месяцев) к дате 1899-12-31, что (что неудивительно) возвращает то же значение: 2017-07-31. 1899 + 117 = 2016. 12 + 7 = 7, потому что мы работаем в месяцах, поэтому перенесите 1 в год: 2017-07-31.

1 голос
/ 13 марта 2020

Как объяснено в документации для dateadd():

Если верно следующее:

  • datepart - это месяц
  • месяц даты имеет больше дней, чем месяц возврата
  • день даты не существует в месяце возврата

Затем DATEADD возвращает последний день месяца возврата.

...