【问题标题】:Get past date before days / month / years using date functions in sql使用sql中的日期函数获取天/月/年之前的过去日期
【发布时间】:2018-04-14 02:23:06
【问题描述】:

我正在尝试根据用户输入的年月日来计算出生日期。

下面的例子将给出我想要达到的目标的一些想法。

基本上有两个步骤

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

2 ) 从输入的日/月和年获取日期。例如 29 年 8 个月零 28 天应该返回 04 Feb 1988

第 1 步工作正常,但对于案例 2,当年份为闰年且月份为 2 月时,我遇到了问题。

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

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

还有其他方法我应该看看吗?

【问题讨论】:

  • 您使用的是 DATEDIFF 功能吗?您可以在您的问题中添加什么 SQL 来帮助我们了解您目前的情况?
  • 代码在我办公室的系统里。我明天会分享。基本上我已经使用了 DATEADD 函数
  • 您在发布问题时分享您的努力。如果您直到明天才能做到这一点,那么明天发布您的问题。以及为什么您需要一张图片(这会花费移动用户的数据费用,并且在许多公司代理后不可见)来表示我想让用户输入他们的出生日期并显示他们的年数、月数和天数是
  • 感谢@KenWhite 的建议,但我面临的问题不是显示从出生日期算起的年、月和天数。我想从年、月和天输入。所以为了更好地理解问题,我附上了图像。我一定会记住下次不要包含不必要的图形表示。
  • 关键是您不需要图像,因为它没有增加任何价值。用文字说明问题。由于我已经指出的原因,只有在没有其他方式来描述或演示问题时才应使用图像。这并没有改变在帖子中展示你的努力的需要,而不是明天。

标签: sql-server date


【解决方案1】:

如果您对 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')

【讨论】:

  • 示例 2 对我来说很有魅力,但主要有两个问题。它不适用于闰年 2 月 29 日。前任。 29/02/1988 以及当我们将月份和日期传递为 0 时,它为 D 返回 NULL
  • @BakerStreet221 我再看看。
  • @BakerStreet221 抱歉耽搁了,我被拉走了。我想我现在明白了。查看更新的示例 2
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-31
  • 2019-04-10
相关资源
最近更新 更多