SQL Server - 在选择查询中计算日,月,年的年龄

时间:2016-10-12 14:47:01

标签: sql sql-server

我找到了几个帮助我解决这个问题的例子,但没有一个可用于数据表。

我在表格中列出了名称和日期,我想根据今天的日,月和年来计算每个人的年龄,例如:

   Name          DOB        Years      Months      Days
Joe Bloggs     01/10/2012     4          0         11
Steven Wright  29/02/2004     12         7         13

这是我目前使用的查询:

SELECT
Person.Name,
Person.DOB,
DATEDIFF(yy, Person.DOB, GETDATE()) - CASE WHEN (MONTH(Person.DOB) > MONTH(GETDATE())) OR (MONTH(Person.DOB) = MONTH(GETDATE()) AND DAY(Person.DOB) > DAY(GETDATE())) THEN 1 ELSE 0 END AS Years,
DATEDIFF(m, Person.DOB, GETDATE()) - CASE WHEN DAY(Person.DOB) > DAY(GETDATE()) THEN 1 ELSE 0 END AS Months,
DATEDIFF(d, Person.DOB, GETDATE()) AS Days
FROM Person
Where DOB IS NOT NULL

这将从上面的SQL查询中显示Joe Bloggs的以下内容:

   Name            DOB        Years      Months      Days
Joe Bloggs      01/10/2012      4          48        1472

基本上发生的事情是,这些年份不会从几个月中扣除,等等......所以这是总天数,总月数和总年数,而不是如上所示的分解。

如何使用名为Family的数据表修改上述查询以使其工作,字段为NameDOB < / p>

4 个答案:

答案 0 :(得分:1)

怎么样

declare @dob date = '22Aug1982'
declare @Yr int = 2016
declare @mon int = 6
declare @dom int = 13
Select @Yr - Year(@dob) - 1 + 
case when @mon > Month(@dob) then 1
     when @mon < Month(@dob) then 0
     else case when @dom >= Day(@dob) then 1 
else 0 end end 

但我建议你在表中添加一个计算列:

alter table Family
    add AgeYears
    as Year(getdate()) - Year(dob) - 1 +
        case when Month(getdate()) > month(dob) then 1
             when month(getdate()) < month(dob) then 0
             else case when day(getdate()) >= day(dob) then 1
         else 0 end end

如果您还需要额外的月份和旧月,请为这些添加列:

alter table Family
    add AgeYears as Year(getdate()) - Year(dob) - 1 +
           case when Month(getdate()) > month(dob) then 1
                when month(getdate()) < month(dob) then 0
                else case when day(getdate()) >= day(dob) then 1
             else 0 end end,
    AgeMonths as case when Month(getdate()) >= Month(dob) 
             then Month(getdate()) - month(dob)
             else month(dob) - Month(getdate()) end,
    AgeDays as case when day(getdate()) >= day(dob) 
             then day(getdate()) - day(dob)
             else day(dob) - day(getdate()) end

答案 1 :(得分:1)

我在TVF看起来有点矫枉过正,但它非常快速准确

Declare @YourTable Table (Name varchar(25),DOB Date)
Insert Into @YourTable values
('Joe Bloggs'   ,'2012-10-01'),
('Steven Wright','2004-02-29') 

Select A.*
      ,B.*
 From  @YourTable A
 Cross Apply [dbo].[udf-Date-Elapsed](A.DOB,GetDate()) B

返回

Name            DOB         Years   Months  Days    Hours   Minutes Seconds
Joe Bloggs      2012-10-01  4       0       11      11      3       17
Steven Wright   2004-02-29  12      7       13      11      3       17

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] ('1964-07-29 09:35:00.000',GetDate())

答案 2 :(得分:1)

尝试下面的解决方案,我没有测试过它可能有效:

DECLARE @DOB DATE = '1991-11-19'
SELECT  DATEDIFF(M,@DOB,GETDATE())/12 [Year],
        DATEDIFF(M,@DOB,GETDATE())%12 [Month],
        DATEDIFF(DD,
        CASE
            WHEN DATEADD(MM,DATEDIFF(MM,@DOB,GETDATE()),@DOB) > GETDATE()
                THEN DATEADD(MM,DATEDIFF(MM,@DOB,GETDATE())-1,@DOB)
            ELSE DATEADD(MM,DATEDIFF(MM,@DOB,GETDATE()),@DOB)
        END,
        GETDATE()) [Day]

答案 3 :(得分:1)

我在这个问题上尝试了一些边界条件!如果你愿意,到目前为止似乎还可以。

declare @dob datetime = '19800229';           --date of birth
DECLARE @DAT datetime = '20160301';           --calculation date

SELECT YEAR(@DAT) - YEAR(@dob) - 
            CASE WHEN MONTH(@DAT) < MONTH(@DOB) OR MONTH(@DAT) = MONTH(@DOB) AND DAY(@DAT) < DAY(@DOB) THEN 1 ELSE 0 END YEARS,
        (YEAR(@DAT)*12 - YEAR(@dob)*12 + MONTH(@DAT) - MONTH(@dob) - 
        CASE WHEN DAY(@DAT) < DAY(@DOB) THEN 1 ELSE 0 END) % 12 MONTHS,

    datediff(day,
    dateadd(month,(YEAR(@DAT)*12 - YEAR(@dob)*12 + MONTH(@DAT) - MONTH(@dob) - 
        CASE WHEN DAY(@DAT) < DAY(@DOB) THEN 1 ELSE 0 END) % 12,

    dateadd(year, YEAR(@DAT) - YEAR(@dob) - 
            CASE WHEN MONTH(@DAT) < MONTH(@DOB) OR MONTH(@DAT) = MONTH(@DOB) AND DAY(@DAT) < DAY(@DOB) THEN 1 ELSE 0 END ,@dob)
            ),@DAT) DAYS