在SQL Server中使用DATEDIFF的最准确方法是什么?

Sta*_*ace 3 t-sql sql-server datediff sql-server-2005

我有两个带有以下表达式的计算列(MonthsInService和YearsInService).

MonthsInService = (datediff(month,[DateEngaged],getdate()))

YearsInService = (datediff(month,[DateEngaged],getdate())/(12))

现在,如果例如DateEngaged = 2012-April-09和getdate()是2013年4月 - 08,则MonthsInService返回12并且YearsInService为1.

我的申请要求YearsInService为零,因为在员工成立一周年之前还有一天要走.

我甚至不确定如何最好地处理MonthsInService列,因为几个月有不同的天数.

Dam*_*ver 5

不幸的是,DATEDIFF计算元素的转换次数,而不是两个日期之间差异的通常的人类直觉(例如DATEDIFF(year,'20121231','20130101'),1,即使没有多少人会说有一年的差异).

我使用的解决方案有点重复,但不需要单独的功能,并且总是得到例如闰年:

declare @T table (
    DateEngaged datetime not null,
    MonthsInService as CASE
        WHEN DATEADD(month,DATEDIFF(month,DateEngaged,GETDATE()),DateEngaged) > GETDATE()
            THEN DATEDIFF(month,DateEngaged,GETDATE()) - 1
            ELSE DATEDIFF(month,DateEngaged,GETDATE())
        END,
    YearsInService as CASE
        WHEN DATEADD(year,DATEDIFF(year,DateEngaged,GETDATE()),DateEngaged) > GETDATE()
            THEN DATEDIFF(year,DateEngaged,GETDATE()) - 1
            ELSE DATEDIFF(year,DateEngaged,GETDATE())
        END
)

insert into @T (DateEngaged) values ('20120409'),('20120408')

select * from @T
Run Code Online (Sandbox Code Playgroud)

生产:

DateEngaged             MonthsInService YearsInService
----------------------- --------------- --------------
2012-04-09 00:00:00.000 11              0
2012-04-08 00:00:00.000 12              1
Run Code Online (Sandbox Code Playgroud)

它的工作原理是"如果我们采取由DATEDIFF它产生的天真答案,它是否给出了一个太高的答案?" - 如果是这样,我们只从它给出的答案中减去一个.DATEDIFF应该只能超过1.