一直卡在这个上面有一段时间了。假设我有一个 Client
表,如下所示:
Name BirthDayNum BirthMonthNum BirthYearNum
--------------------------------------------------
John 23 12 1965
Jane 4 9 1975
Joe 6 3 1953
目前我正在使用这种语法计算年龄:(抱歉,如果难以阅读)
DATEDIFF(year, CONVERT(datetime, CAST(client.BirthMonthNum AS varchar(2))
+ '-' + CAST(client.BirthDayNum AS varchar(2))
+ '-' + CAST(client.BirthYearNum AS varchar(4)), 101), GETDATE())
- (CASE WHEN dateadd(YY, DATEDIFF(year, CONVERT(datetime, CAST(client.BirthMonthNum AS varchar(2))
+ '-' + CAST(client.BirthDayNum AS varchar(2))
+ '-' + CAST(client.BirthYearNum AS varchar(4)), 101), GETDATE()),
CONVERT(datetime, CAST(client.BirthMonthNum AS varchar(2))
+ '-' + CAST(client.BirthDayNum AS varchar(2))
+ '-' + CAST(client.BirthYearNum AS varchar(4)), 101)) > getdate() THEN 1 ELSE 0 END) AS 'Client Age'
这将给我年龄。当然,如果我想要几个月,我只需将 DATEDIFF(year
更改为 month
。所以,我现在要做的是这个。
继续计算年龄,但我不想返回年或月,而是想以年和月为单位返回年龄,而且还要在值中连接“y”和“m”。前任。上面的 Jane 41y 11m。
所以基本上我想弄清楚如何向返回值添加一个字符,以及如何计算年计算之外的剩余月份。
如有任何帮助,我们将不胜感激!
最佳答案
厌倦了在日期计算上纠缠不清,我创建了一个表值函数来计算以年、月、日、小时、分钟和秒为单位的耗时。
示例
Declare @YourTable table (Name varchar(50),BirthDayNum int, BirthMonthNum int, BirthYearNum int)
Insert Into @YourTable values
('John', 23, 12, 1965),
('Jane', 4, 9, 1975),
('Joe', 6, 3, 1953)
Select A.Name
,B.*
,Age = concat(C.Years,'y ',C.Months,'m')
From @YourTable A
Cross Apply (Select DOB = DateFromParts(A.BirthYearNum,A.BirthMonthNum,A.BirthDayNum)) B
Cross Apply [dbo].[udf-Date-Elapsed](B.DOB,GetDate()) C
返回
Name DOB Age
John 1965-12-23 51y 3m
Jane 1975-09-04 41y 6m
Joe 1953-03-06 64y 0m
UDF - 可能看起来有点矫枉过正,但它的性能非常好
CREATE FUNCTION [dbo].[udf-Date-Elapsed] (@D1 DateTime,@D2 DateTime)
Returns Table
Return (
with cteBN(N) as (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
cteRN(R) as (Select Row_Number() Over (Order By (Select NULL))-1 From cteBN a,cteBN b,cteBN c),
cteYY(N,D) as (Select Max(R),Max(DateAdd(YY,R,@D1))From cteRN R Where DateAdd(YY,R,@D1)<=@D2),
cteMM(N,D) as (Select Max(R),Max(DateAdd(MM,R,D)) From (Select Top 12 R From cteRN Order By 1) R, cteYY P Where DateAdd(MM,R,D)<=@D2),
cteDD(N,D) as (Select Max(R),Max(DateAdd(DD,R,D)) From (Select Top 31 R From cteRN Order By 1) R, cteMM P Where DateAdd(DD,R,D)<=@D2),
cteHH(N,D) as (Select Max(R),Max(DateAdd(HH,R,D)) From (Select Top 24 R From cteRN Order By 1) R, cteDD P Where DateAdd(HH,R,D)<=@D2),
cteMI(N,D) as (Select Max(R),Max(DateAdd(MI,R,D)) From (Select Top 60 R From cteRN Order By 1) R, cteHH P Where DateAdd(MI,R,D)<=@D2),
cteSS(N,D) as (Select Max(R),Max(DateAdd(SS,R,D)) From (Select Top 60 R From cteRN Order By 1) R, cteMI P Where DateAdd(SS,R,D)<=@D2)
Select [Years] = cteYY.N
,[Months] = cteMM.N
,[Days] = cteDD.N
,[Hours] = cteHH.N
,[Minutes] = cteMI.N
,[Seconds] = cteSS.N
From cteYY,cteMM,cteDD,cteHH,cteMI,cteSS
)
--Max 1000 years
--Select * from [dbo].[udf-Date-Elapsed] ('1991-09-12 21:00:00.000',GetDate())
只是为了说明
没有任何二次字符串操作的 TVF 将返回
Select A.Name
,B.*
From @YourTable A
Cross Apply [dbo].[udf-Date-Elapsed](DateFromParts(A.BirthYearNum,A.BirthMonthNum,A.BirthDayNum),GetDate()) B
EDIT - READ ONLY VERSION
Select A.Name
,B.*
,Age = concat(DateDiff(MONTH,B.DOB,GetDate())/12,'y ',DateDiff(MONTH,B.DOB,GetDate()) % 12,'m')
From @YourTable A
Cross Apply (Select DOB = DateFromParts(A.BirthYearNum,A.BirthMonthNum,A.BirthDayNum)) B
关于sql - T-SQL : calculate age then add character to result,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43126223/