计算 SQL 岁
Calculating Age of Years in SQL
我需要一些关于 SQL Server 2012 的帮助,试图计算报告的老化年份字段。
基本上,我有两个字段 StartDateTime 和 EndDateTime,下面是一些示例数据:
StartDateTime EndDateTime
2006-10-10 16:08:13.523 2008-04-11 00:00:00.000
2016-05-11 13:03:48.093 2016-06-16 00:00:00.000
2016-08-01 12:44:42.990 2016-08-01 00:00:00.000
2016-05-20 17:33:27.957 2016-05-25 00:00:00.000
2006-10-19 21:41:41.350 NULL
我目前正在尝试制作一个 AgingYears 字段来计算两个字段之间的老化年份(尽可能准确。)并且当 EndDateTime 为 NULL 时,它应该计算 GETDATE() 和 StartDateTime 之间的差异。当 StartDateTime 大于 EndDateTime(我不知道为什么我有这样的数据,但我有),那么它应该 return 返回 0.
我尝试根据我发现的相关网站编写一些代码,但这对我帮助不大,这就是我遇到的问题:
DATEDIFF(YY, StartDateTime, EndDateTime) -
CASE
WHEN DATEADD(YY,DATEDIFF(YY,StartDateTime, EndDateTime),StartDateTime)
> A.[END_DTTM]
THEN DATEDIFF(YY, StartDateTime, EndDateTime)- 1
ELSE DATEDIFF(YY, StartDateTime, EndDateTime)
END AS AgeInYears,
任何对我的代码的帮助将不胜感激。
小心闰年。你希望2月29日到2月28日如何对待?
case
when year(coalesce(EndDateTime, getdate()) > year(StartDateTime)
then
datediff(year, StartDateTime, coalesce(EndDateTime, getdate())) -
case
when
EndDateTime is not null and
datepart(month, EndDateTime) < datepart(month, StartDateTime)
or datepart(month, EndDateTime) = datepart(month, StartDateTime)
and datepart(day, EndDateTime) < datepart(day, StartDateTime)
then 1
when
EndDateTime is null and
datepart(month, getdate()) < datepart(month, StartDateTime)
or datepart(month, getdate()) = datepart(month, StartDateTime)
and datepart(day, getdate()) < datepart(day, StartDateTime)
then 1
else 0
end
else 0
end
我将 EndDateTime
和 getdate()
情况分开主要是因为在长行上没有滚动条看起来更好。
这里有一种方法可以调整该逻辑并捕捉闰日条件,将其视为整年,即使日期并不严格重合。如果按照我上面写的方式保持 "split" 逻辑,则需要在两个分支中复制此表达式(替换为 getdate() for
EndDateTimeeverywhere except the
is null` 测试)。
when
EndDateTime is not null and
datepart(month, EndDateTime) < datepart(month, StartDateTime)
or datepart(month, EndDateTime) = datepart(month, StartDateTime)
and datepart(day, EndDateTime) < datepart(day, StartDateTime)
and not -- here's one way to catch the leap day condition
(
-- adding one day this way is deprecated and only works with datetime
and datepart(month, StartDateTime + 1) > datepart(month, StartDateTime)
and datepart(month, EndDateTime + 1) > datepart(month, EndDateTime)
)
顺便说一句,一旦您理解了这种方法,就有一种方法可以使用 yyyymmdd 格式的数字算术来压缩相同的逻辑。
(
cast(convert(varchar(8), @EndDateTime, 120) as int) -
cast(convert(varchar(8), @StartDateTime, 120) as int)
) / 10000
上面所有复杂的逻辑都是借用了减法中的年位。这几乎是一回事。
我觉得应该是这样的:
SELECT StartDate
, EndDate
, CASE
WHEN DATEDIFF(YY, StartDate, ISNULL(EndDate, GETDATE())) < 0
THEN 0
ELSE DATEDIFF(YY, StartDate, ISNULL(EndDate, GETDATE()))
END AS AgingYears
FROM YourTableName
我需要一些关于 SQL Server 2012 的帮助,试图计算报告的老化年份字段。
基本上,我有两个字段 StartDateTime 和 EndDateTime,下面是一些示例数据:
StartDateTime EndDateTime
2006-10-10 16:08:13.523 2008-04-11 00:00:00.000
2016-05-11 13:03:48.093 2016-06-16 00:00:00.000
2016-08-01 12:44:42.990 2016-08-01 00:00:00.000
2016-05-20 17:33:27.957 2016-05-25 00:00:00.000
2006-10-19 21:41:41.350 NULL
我目前正在尝试制作一个 AgingYears 字段来计算两个字段之间的老化年份(尽可能准确。)并且当 EndDateTime 为 NULL 时,它应该计算 GETDATE() 和 StartDateTime 之间的差异。当 StartDateTime 大于 EndDateTime(我不知道为什么我有这样的数据,但我有),那么它应该 return 返回 0.
我尝试根据我发现的相关网站编写一些代码,但这对我帮助不大,这就是我遇到的问题:
DATEDIFF(YY, StartDateTime, EndDateTime) -
CASE
WHEN DATEADD(YY,DATEDIFF(YY,StartDateTime, EndDateTime),StartDateTime)
> A.[END_DTTM]
THEN DATEDIFF(YY, StartDateTime, EndDateTime)- 1
ELSE DATEDIFF(YY, StartDateTime, EndDateTime)
END AS AgeInYears,
任何对我的代码的帮助将不胜感激。
小心闰年。你希望2月29日到2月28日如何对待?
case
when year(coalesce(EndDateTime, getdate()) > year(StartDateTime)
then
datediff(year, StartDateTime, coalesce(EndDateTime, getdate())) -
case
when
EndDateTime is not null and
datepart(month, EndDateTime) < datepart(month, StartDateTime)
or datepart(month, EndDateTime) = datepart(month, StartDateTime)
and datepart(day, EndDateTime) < datepart(day, StartDateTime)
then 1
when
EndDateTime is null and
datepart(month, getdate()) < datepart(month, StartDateTime)
or datepart(month, getdate()) = datepart(month, StartDateTime)
and datepart(day, getdate()) < datepart(day, StartDateTime)
then 1
else 0
end
else 0
end
我将 EndDateTime
和 getdate()
情况分开主要是因为在长行上没有滚动条看起来更好。
这里有一种方法可以调整该逻辑并捕捉闰日条件,将其视为整年,即使日期并不严格重合。如果按照我上面写的方式保持 "split" 逻辑,则需要在两个分支中复制此表达式(替换为 getdate() for
EndDateTimeeverywhere except the
is null` 测试)。
when
EndDateTime is not null and
datepart(month, EndDateTime) < datepart(month, StartDateTime)
or datepart(month, EndDateTime) = datepart(month, StartDateTime)
and datepart(day, EndDateTime) < datepart(day, StartDateTime)
and not -- here's one way to catch the leap day condition
(
-- adding one day this way is deprecated and only works with datetime
and datepart(month, StartDateTime + 1) > datepart(month, StartDateTime)
and datepart(month, EndDateTime + 1) > datepart(month, EndDateTime)
)
顺便说一句,一旦您理解了这种方法,就有一种方法可以使用 yyyymmdd 格式的数字算术来压缩相同的逻辑。
(
cast(convert(varchar(8), @EndDateTime, 120) as int) -
cast(convert(varchar(8), @StartDateTime, 120) as int)
) / 10000
上面所有复杂的逻辑都是借用了减法中的年位。这几乎是一回事。
我觉得应该是这样的:
SELECT StartDate
, EndDate
, CASE
WHEN DATEDIFF(YY, StartDate, ISNULL(EndDate, GETDATE())) < 0
THEN 0
ELSE DATEDIFF(YY, StartDate, ISNULL(EndDate, GETDATE()))
END AS AgingYears
FROM YourTableName