Разница между датами — сервер sql

Мне нужно получить следующий результат между двумя датами:

date_start = 01.01.2010
date_end = 21.10.2012

результат: 1 год, 9 месяцев и 20 дней.

Я попробовал код ниже, но это не сработало. Иногда он возвращает отрицательные даты:

SELECT CAST(DATEDIFF(yy, date_start, date_end) AS varchar(4)) +' year '+
       CAST(DATEDIFF(mm, DATEADD(yy, DATEDIFF(yy,date_start , date_end), date_start), date_end) AS varchar(2)) +' month '+
       CAST(DATEDIFF(dd, DATEADD(mm, DATEDIFF(mm, DATEADD(yy, DATEDIFF(yy, date_start, date_end), date_start), date_end), DATEADD(yy, DATEDIFF(yy, date_start, date_end), date_start)), date_end) AS varchar(2)) +' day' AS result

Спасибо!


person Willian Cândido    schedule 25.09.2012    source источник
comment
вы уверены, что ожидаемый результат 1 год 9 месяцев или 2 года 9 месяцев   -  person rs.    schedule 25.09.2012
comment
А что вы хотите, если дата начала 2010-01-19 или 2010-01-21?   -  person Aaron Bertrand    schedule 25.09.2012
comment
Независимо от того, как вы получите результат, будьте осторожны с тем, что вы делаете с выводом. Помните, что месяц – это не точная единица времени. Если ваш пользователь знает об одном из моментов, например, через три месяца или три месяца назад, это нормально. Но без точки отсчета месяц не имеет смысла.   -  person Matt Johnson-Pint    schedule 25.09.2012


Ответы (3)


Это может неправильно обрабатывать високосные годы, если @s или @e соседствуют с ними, но в остальном это должно быть довольно близко:

DECLARE @s DATE, @e DATE

SELECT @s = '20100101', @e = '20121021';

SELECT y + ' year(s), ' + m + ' month(s) and ' + d + ' day(s).'
FROM
(
  SELECT 
    RTRIM(y), 
    RTRIM(m - CASE WHEN pd < 0 THEN 1 ELSE 0 END),
    RTRIM(CASE WHEN pd < 0 THEN nd ELSE pd END)
  FROM 
  (
    SELECT
      DATEDIFF(MONTH, @s, @e) / 12, 
      DATEDIFF(MONTH, @s, @e) % 12,
      DATEDIFF(DAY, @s, DATEADD(MONTH, -DATEDIFF(MONTH, @s, @e), @e)),
      DATEDIFF(DAY, @s, DATEADD(MONTH, 1-DATEDIFF(MONTH, @s, @e), @e))
  ) AS x (y, m, pd, nd)
) AS y (y, m, d);

Выход:

2 year(s), 9 month(s) and 20 day(s).

Если учет дополнительного дня в високосном году имеет решающее значение, я уверен, что его можно скорректировать, чтобы справиться с этим. Хотя при минимальном тестировании я не смог увидеть ни одного случая, когда он сломается (просто кажется, что он не должен работать).

person Aaron Bertrand    schedule 25.09.2012

Попробуй это

DECLARE @months decimal (5,2)
SELECT @months = DATEDIFF(month, '01/22/2010','10/21/2012')/12.0

;WITH CTE AS 
(
SELECT FLOOR(@months) AS years,(@months-FLOOR(@months)) * 12 AS months
)
SELECT years, CAST(months as int) months, 
case when day('01/22/2010') > day('10/21/2012')  
then day('10/21/2012') +  
datediff(day,'01/22/2010',dateadd(month,datediff(month,0,'01/22/2010')+1,0))- 1
ELSE day('10/21/2012')-day('01/22/2010') end
from cte
person rs.    schedule 25.09.2012
comment
Это не выводит дни (а также не учитывает високосные годы, когда это происходит). - person Aaron Bertrand; 25.09.2012
comment
Теперь измените дату начала на 2010-01-22... Я заметил, что у меня похожая проблема. - person Aaron Bertrand; 25.09.2012

вы можете получить разницу в датах, используя функцию, см. также этот http://atikpassion.blogspot.com/2014/01/get-difference-between-two-dates-in.html

person Mohammad Atiour Islam    schedule 21.01.2014