как получить количество месяцев между двумя датами в sql server 2005

У меня есть столбец в таблице SQL Server 2005, в которой должно быть указано количество месяцев, в течение которых сотрудник работал.

Поскольку у меня также есть дата, когда сотрудник был нанят, я хочу, чтобы столбец «months_In_Service» был вычисляемым столбцом.

Теперь, если я использую DATEDIFF(month,[DateEngaged],GETDATE()) в качестве формулы для вычисляемого столбца месяцев службы, результаты будут правильными несколько раз, а иногда неверными.

Каким будет более надежный способ получить количество месяцев между значением DateEngaged и текущей датой? Какую формулу следует использовать в моем вычисляемом столбце?


person StackTrace    schedule 13.01.2010    source источник
comment
Не могли бы вы привести несколько примеров того, что вы имеете в виду, когда говорите, что иногда они верны, а иногда нет.   -  person My Other Me    schedule 13.01.2010
comment
Не могли бы вы изменить это (отредактировать) и установить sql-server-2005 (или даже просто sql-server)? Обратите внимание на черточки. Здесь есть пользователи, которые игнорируют вопросы SQL Server (а не свои знания), но интересуются вопросами SQL.   -  person Jürgen A. Erhard    schedule 13.01.2010
comment
DateEngaged = '20/12/2009 CurrentDate = '13/1/2010 Это дает мне месяцы службы как 1 с использованием формулы datediff(month,[DateEngaged],getdate()+(1)) Это также дает годы службы как 1 используя формулу datediff(year,[DateEngaged],getdate()+(1))   -  person StackTrace    schedule 13.01.2010
comment
И какой результат вы ожидаете?   -  person My Other Me    schedule 13.01.2010


Ответы (4)


Что-то вроде (возможно, нужно поменять местами 1 и 0, не проверено)

datediff(month,[DateEngaged],getdate()) +
 CASE WHEN DATEPART(day, [DateEngaged]) < DATEPART(day, getdate()) THEN 1 ELSE 0 END

DATEDIFF измеряет границы месяца, например, время 00:00 1-го числа каждого месяца, а не годовщины дня месяца.

Изменить: увидев комментарий OP, вы должны вычесть 1, если день начала> день окончания

DATEDIFF (month, DateEngaged, getdate()) -
 CASE
   WHEN DATEPART(day, DateEngaged) > DATEPART(day, getdate()) THEN 1 ELSE 0
 END

Таким образом, с 20 декабря по 13 января DATEDIFF дает 1, а затем 20> 13, поэтому вычтите 1 = ноль месяцев.

person gbn    schedule 13.01.2010
comment
это, кажется, работает правильно, я просто собираюсь проверить это на всякий случай. - person StackTrace; 13.01.2010
comment
Вы когда-нибудь проверяли, что происходит, когда сотрудник занят 31 октября, а текущая дата — 30 ноября? Эта подпрограмма возвращает 0 месяцев, но на самом деле практически каждое бизнес-требование, которое я могу себе представить, говорит, что это месяц. Нашел это в поисках решения этой самой проблемы. Все еще смотрит...... - person Ron; 28.03.2016
comment
Не блестящее решение того, что объясняет @Ron? - person toscanelli; 23.08.2017

Тот же подход, что и gbn, но с меньшим количеством нажатий клавиш :-)

SELECT 
    DATEDIFF(MONTH, DateEngaged, GETDATE()) +
    CASE 
        WHEN DAY(DateEngaged) < DAY(GETDATE())
        THEN 1 
        ELSE 0 
    END
person Frank Kalis    schedule 13.01.2010

Возможно, вы хотите что-то вроде:

(year(getdate())-year([DateEngaged]))*12+(month(getdate())-month([DateEngaged]))
person My Other Me    schedule 13.01.2010

Если вы предполагаете, что месяц означает 30 дней, вы также можете округлить

round((datediff(day,[DateEngaged],getdate()))/30.00,0)
person adopilot    schedule 13.01.2010
comment
я точно хочу, чтобы месяц означал 30 дней и год двенадцать месяцев по 30 дней (каждый!!). - person StackTrace; 13.01.2010
comment
Это дрейфует все дальше и дальше с течением времени. Через 6 лет погрешность целый месяц гарантирована - person gbn; 13.01.2010