使用sql中的日期函数获取日/月/年之前的过去日期

时间:2017-11-01 17:24:39

标签: sql-server date

我正在尝试从用户输入的年,月和日计算出生日期。

下面的示例将让我们了解到我想要实现的目标。

基本上有两个步骤

1)从出生日期开始的日期/月份和年份(从用户输入的日期)。例如1988年2月4日应该返回29年8个月28天

2)从输入的日期/月份和年份中获取日期。例如29年​​8个月和28天应该回到1988年2月4日

第1步工作正常,但在案例2中,当年份为闰年,月份为2月时,我面临问题。

我已经花了一天半时间寻找解决方案,但非有用,因为它们只对案例1有帮助。

我还尝试将当前日期和dob之间的总天数计算为365.25,然后从当前日期减去它,但面临同样的问题。

我应该看看其他方法吗?Image description

1 个答案:

答案 0 :(得分:2)

如果您对TVF持开放态度,我可以计算以年,月,日,小时,分钟和秒为单位的经过时间。您可以删除(或忽略)小时,分钟和秒

现在,我从未考虑过解决相反的问题,但可以使用相同的功能来完成。

此功能非常准确且高效。你永远不必担心错误的日期计算。

在下面的示例中,我使用了今天的2017-11-01日期,但您可以使用GetDate()替换

示例1

Declare @Date date = '1988-02-04'

Select * from [dbo].[tvf-Date-Elapsed](@Date,'2017-11-01')

<强>返回

Years   Months  Days    Hours   Minutes Seconds
29      8       28      0       0       0

示例2

Declare @Y int  = 29
Declare @M int  = 8
Declare @D int  = 28

Select D=max(D)
 From  (
         Select Top (500) D= DateAdd(DAY,-1+Row_Number() over (Order by (Select NULL)), DateAdd(DAY,((@Y*366)+(@M*31)+@D)*-1,'2017-11-01'))
         From master..spt_values n1
        ) A
 Cross Apply [dbo].[tvf-Date-Elapsed](A.D,'2017-11-01')
 Where Years =@Y 
   and Months=IIF(@M=0,Months,@M)
   and Days  =IIF(@D=0,Days,@D)

<强>返回

D
1988-02-04 00:00:00.000

UDF如果有兴趣

CREATE FUNCTION [dbo].[tvf-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
          --,[Elapsed] = Format(cteYY.N,'0000')+':'+Format(cteMM.N,'00')+':'+Format(cteDD.N,'00')+' '+Format(cteHH.N,'00')+':'+Format(cteMI.N,'00')+':'+Format(cteSS.N,'00')
     From  cteYY,cteMM,cteDD,cteHH,cteMI,cteSS
)
--Max 1000 years
--Select * from [dbo].[tvf-Date-Elapsed] ('1991-09-12 21:00:00.000',GetDate())
--Select * from [dbo].[tvf-Date-Elapsed] ('2017-01-01 20:30:15','2018-02-05 22:58:35')