[英]What is the most accurate way of using DATEDIFF in SQL Server?
I have two computed columns (MonthsInService and YearsInService) with the following expressions.我有两个带有以下表达式的计算列(MonthsInService 和 YearsInService)。
MonthsInService = (datediff(month,[DateEngaged],getdate()))
MonthsInService = (datediff(month,[DateEngaged],getdate()))
YearsInService = (datediff(month,[DateEngaged],getdate())/(12))
YearsInService = (datediff(month,[DateEngaged],getdate())/(12))
Now if for example DateEngaged = 2012-April-09 and getdate() is 2013-April-08, MonthsInService returns 12 and YearsInService is 1.现在,如果 DateEngaged = 2012-April-09 并且 getdate() 为 2013-April-08,则 MonthsInService 返回 12 并且 YearsInService 为 1。
My application requires that YearsInService be Zero since there is still one day to go before the employees first Anniversary.我的应用程序要求 YearsInService 为零,因为距离员工一周年还有一天。
Am not even sure how to best handle the MonthsInService column since months have varying number of days.我什至不确定如何最好地处理 MonthsInService 列,因为月份有不同的天数。
Unfortunately, DATEDIFF
computes the number of transitions of the element, rather than the usual, human intuition of the difference between two dates (eg DATEDIFF(year,'20121231','20130101')
is 1, even though not many people would say that there's a difference of a year). 不幸的是, DATEDIFF
计算元素的转换次数,而不是通常的人类对两个日期之间差异的直觉(例如DATEDIFF(year,'20121231','20130101')
是1,尽管没有多少人会说有一年的差异)。
The solution I'd use is a bit repetitive, but doesn't need a separate function, and always gets eg leap years correct: 我使用的解决方案有点重复,但不需要单独的功能,并且总是得到例如闰年:
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
Produces: 生产:
DateEngaged MonthsInService YearsInService
----------------------- --------------- --------------
2012-04-09 00:00:00.000 11 0
2012-04-08 00:00:00.000 12 1
It works by asking "If we take the naive answer produced by DATEDIFF
, does it given an answer that's too high by 1?" 它的工作原理是“如果我们采用DATEDIFF
产生的天真答案,它是否给出了一个太高的答案?” - and if so, we just subtract one from the answer it gives. - 如果是这样,我们只从它给出的答案中减去一个。 DATEDIFF
should only ever be over by 1. DATEDIFF
应该只能超过1。
Via using day
you can reach the result: 通过使用day
您可以达到结果:
select
datediff(month,'2012-April-09','2013-April-08') MonthsInService
,datediff(day,'2012-April-09','2013-April-08')/365 YearsInService
Output : 输出 :
12 0
or use function for maximum precision: 或使用函数以获得最大精度:
CREATE FUNCTION [dbo].[getFullYears]
(
@dateX datetime,
@dateY datetime
)
RETURNS int
AS
BEGIN
DECLARE @y int
SET @y =DATEDIFF(year,@dateX,@dateY)
IF (@dateY < DATEADD(year, @y, @dateX)) SET @y = @y -1
RETURN @y
END
select dbo.getFullYears('2012-April-09','2013-April-09') --1
select dbo.getFullYears('2012-April-09','2013-April-08') --0
For months calculation you can refer here: Calculating number of full months between two dates in SQL 对于月计算,您可以在此处参考: 计算SQL中两个日期之间的完整月数
DATEDIFF(DAY, CONVERT(date, dtmDOB), DATEDIFF(天,转换(日期,dtmDOB),
CONVERT(date, GETDATE()))*(12.0/365.25)),1))转换(日期,GETDATE()))*(12.0/365.25)),1))
AS TotalMonths, AS TotalMonths,
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.