SQL函数用于特定格式的日期差异

时间:2017-01-15 16:12:42

标签: sql-server

我想找到两个日期之间的确切差异,

declare @a datetime

Set @a = '2017-01-15 10:09:39.500'

Declare @Return varchar(100) 
Set @Return = '';

if(Convert(int, (DATEDIFF(day, @a, getdate()))) >= 1)
Begin
    Set @Return += Convert(varchar(10), (DATEDIFF(day, @a, getdate()))) + ' Day ';
End

if(Convert(int, (DATEDIFF(HOUR, @a, getdate()))) >= 1)
Begin
    Set @Return += Convert(varchar(10),(DATEDIFF(HOUR, @a, getdate()))) + ' Hour ';
End

if(Convert(int, (DATEDIFF(MINUTE, @a, getdate()))) >= 1)
Begin
    Set @Return += Convert(varchar(10),(DATEDIFF(MINUTE, @a, getdate()))) + ' Minute ';
End

Select @Return

这会返回日期差异,但这不完全正确。我的意思是它返回类似于" 11小时691分钟"。

但我需要o / p作为11小时的确切分钟。不是两个日期的分钟差异,而是几小时后的分钟差异。

喜欢" 11小时32分钟"或" 13天2小时66分钟" (取决于日期和时间)

但目前我在两个日期的分钟内得到实际差异

例如,如果用户出生于2017-01-14 20:43:38.870' o / p应为1天1小时10分钟

3 个答案:

答案 0 :(得分:1)

这是一个计算确切年龄的TVF Y M D H M S

例如

Select * from [dbo].[udf-Date-Elapsed] ('1991-09-12 21:00:00.000',GetDate())

<强>返回

Years   Months  Days    Hours   Minutes Seconds
25      4       2       14      28      54

作为TVF,它很容易在CROSS APPLY中使用。例如

Declare @Table table (ID int,DOB datetime)
Insert Into @Table values
(1,'1976-07-04 12:00:00'),
(2,'2000-10-22 17:00:00')

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

返回

ID  DOB                     Years   Months  Days    Hours   Minutes Seconds
1   1976-07-04 12:00:00.000 40      6       10      23      33      7
2   2000-10-22 17:00:00.000 16      2       23      18      33      7

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())

答案 1 :(得分:1)

这是我原来答案的一个转折点。这是一个标量udf,它将返回经过时间的字符串

例如:

Select [dbo].[udf-Str-Elapsed] ('1991-09-12 21:00:00.000',GetDate())

<强>返回

25 Years 4 Months 2 Days 16 Hours 1 Minute 47 Seconds 

UDF

CREATE FUNCTION [dbo].[udf-Str-Elapsed] (@D1 DateTime,@D2 DateTime)
Returns varchar(100)
AS 
Begin
    Declare @RetVal varchar(100)
    ;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 @RetVal = IIF(cteYY.N = 0,'',concat(cteYY.N , ' Year',IIF(cteYY.N=1,' ','s ')))
                    +IIF(cteMM.N = 0,'',concat(cteMM.N , ' Month',IIF(cteMM.N=1,' ','s ')))
                    +IIF(cteDD.N = 0,'',concat(cteDD.N , ' Day',IIF(cteDD.N=1,' ','s ')))
                    +IIF(cteHH.N = 0,'',concat(cteHH.N , ' Hour',IIF(cteHH.N=1,' ','s ')))
                    +IIF(cteMI.N = 0,'',concat(cteMI.N , ' Minute',IIF(cteMI.N=1,' ','s ')))
                    +IIF(cteSS.N = 0,'',concat(cteSS.N , ' Second',IIF(cteSS.N=1,' ','s ')))
     From  cteYY,cteMM,cteDD,cteHH,cteMI,cteSS

    Return @RetVal

End

--Max 1000 years
--Select [dbo].[udf-Str-Elapsed] ('1991-09-12 21:00:00.000',GetDate())

答案 2 :(得分:0)

这很简单,但有人需要在那里建议:)
谢谢McNets

Declare @Return varchar(100) 
Set @Return = '';
Declare @TotMinute int
Select @TotMinute = Convert(int,(DATEDIFF(Minute, @a, getdate())))

if(Convert(int,(DATEDIFF(day, @a, getdate()))) >= 1)
Begin
    Set @Return += Convert(varchar,(@TotMinute/1440)) + ' Day ';
End
if(Convert(int,(DATEDIFF(HOUR, @a, getdate()))) >= 1)
Begin
    Set @Return += Convert(varchar,(@TotMinute % 1440) / 60) + ' Hour ';
End
if(Convert(int,(DATEDIFF(MINUTE, @a, getdate()))) >= 1)
Begin
    Set @Return += Convert(varchar,(@TotMinute % 60)) + ' Minute ';
End