Sys*_*nce 2 sql t-sql sql-server
在阅读了该主题并被建议使用后DateDiff。我编写的函数无法提供我想要的答案。客户现在想要完成检查清单需要多长时间。我有一个CreationDate和CompletionDate。我需要知道花了多少年,几个月,几周和几天。如果是2天,则为“ 2天”,没有年份。该功能会扣除年数,然后尝试检查月数,周数和天数。如果可用,则仅给出结果。似乎DateDiff是问题所在...或者我是无法理解的问题DateDiff。它甚至返回一个星期,日期相差4天,这没有任何意义。它应该返回两个日期内的星期数,而不用关心它的开始时间。
这是代码
ALTER FUNCTION [dbo].[DateRangeText]
(@FromDate DATETIME, @ToDate DATETIME)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @Result AS VARCHAR(MAX);
SET @Result = '';
DECLARE @TmpS AS VARCHAR(MAX);
SET @TmpS = '';
DECLARE @Years AS INT;
SET @Years = DATEDIFF(year, @FromDate, @ToDate);
IF (@Years > 0)
BEGIN
IF (@Years = 1)
SET @TmpS = ' Year ';
ELSE
SET @TmpS = ' Years ';
SET @Result = @Result + CAST(@Years AS VARCHAR) + @TmpS;
SET @ToDate = DATEADD(YEAR, -1 * @Years, @ToDate);
END;
DECLARE @Months AS INT;
SET @Months = DATEDIFF(month, @FromDate, @ToDate);
IF (@Months > 0)
BEGIN
IF (@Months = 1)
SET @TmpS = ' Month ';
ELSE
SET @TmpS = ' Months ';
SET @Result = @Result + CAST(@Months AS VARCHAR) + @TmpS;
SET @ToDate = DATEADD(MONTH, -1 * @Months, @ToDate);
END;
DECLARE @Weeks AS INT;
SET @Weeks = DATEDIFF(week, @FromDate, @ToDate);
IF (@Weeks > 0)
BEGIN
IF (@Weeks = 1)
SET @TmpS = ' Week ';
ELSE
SET @TmpS = ' Weeks ';
SET @Result = @Result + CAST(@Weeks AS VARCHAR) + @TmpS;
SET @ToDate = DATEADD(WEEK, -1 * @Weeks, @ToDate);
END;
DECLARE @Days AS INT;
SET @Days = DATEDIFF(day, @FromDate, @ToDate);
IF (@Days > 0)
BEGIN
IF (@Days = 1)
SET @TmpS = ' Day ';
ELSE
SET @TmpS = ' Days ';
SET @Result = @Result + CAST(@Days AS VARCHAR) + @TmpS;
SET @ToDate = DATEADD(WEEK, -1 * @Days, @ToDate);
END;
IF (@Result = '')
SET @Result = 'Same day';
RETURN Rtrim(COALESCE(@Result,''));
END;
Run Code Online (Sandbox Code Playgroud)
由于使用的是函数,请考虑以下表值函数。易于单独使用或作为CROSS APPLY使用。
高效而准确,而不必担心所有其他日期的计算。
例
Select * from [dbo].[tvf-Date-Elapsed] ('1991-09-12 21:00:00.000',GetDate())
Run Code Online (Sandbox Code Playgroud)
退货
Years Months Days Hours Minutes Seconds
26 7 5 13 47 11
Run Code Online (Sandbox Code Playgroud)
TVF如果有兴趣
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')
Run Code Online (Sandbox Code Playgroud)