此问题是问题here
的扩展我试图延长Dane的答案,但结果有点问题。
DECLARE @dateFrom DATETIME
DECLARE @dateTo DATETIME
DECLARE @tmpdate DATETIME
DECLARE @years INT
DECLARE @months INT
DECLARE @days INT
DECLARE @hours INT
DECLARE @minutes INT
DECLARE @seconds INT
DECLARE @milliseconds INT
SELECT @dateFrom = '2011-01-01 11:24:38:100'
SELECT @dateTo = '2012-01-01 11:24:38:110'
SELECT @tmpdate = @dateFrom
SELECT @years = DATEDIFF(yy, @tmpdate, @dateTo)
- CASE WHEN (MONTH(@dateFrom) > MONTH(@dateTo)) OR (MONTH(@dateFrom) = MONTH(@dateTo) AND DAY(@dateFrom) > DAY(@dateTo))
THEN 1
ELSE 0
END
SELECT @tmpdate = DATEADD(yy, @years, @tmpdate)
SELECT @months = DATEDIFF(mm, @tmpdate, @dateTo) - CASE WHEN DAY(@dateFrom) > DAY(@dateTo) THEN 1 ELSE 0 END
SELECT @tmpdate = DATEADD(mm, @months, @tmpdate)
SELECT @days = DATEDIFF(dd, @tmpdate, @dateTo)
SELECT @tmpdate = DATEADD(dd, @days, @tmpdate)
SELECT @hours = DATEDIFF(hh, @tmpdate, @dateTo)
SELECT @tmpdate = DATEADD(hh, @hours, @tmpdate)
SELECT @minutes = DATEDIFF(mi, @tmpdate, @dateTo)
SELECT @tmpdate = DATEADD(mi, @minutes, @tmpdate)
SELECT @seconds = DATEDIFF(ss, @tmpdate, @dateTo)
SELECT @tmpdate = DATEADD(ss, @seconds, @tmpdate)
SELECT @milliseconds = DATEDIFF(ms, @tmpdate, @dateTo)
SELECT
@years AS [years]
, @months AS [months]
, @days AS [days]
, @hours AS [hours]
, @minutes AS [minutes]
, @seconds AS [seconds]
, @milliseconds AS [milliseconds]
结果是:
years months days hours minutes seconds milliseconds
1 0 0 0 0 0 10
但是当我跑步时:
SELECT @dateFrom = '2011-01-02 11:24:38:110'
SELECT @dateTo = '2012-01-01 10:23:37:100'
结果是:
years months days hours minutes seconds milliseconds
0 11 30 -1 -1 -1 -10
帮助将不胜感激!
答案 0 :(得分:2)
答案是正确的,但它显示为负值。您需要使用abs来返回正值
SELECT
@years AS [years]
, abs(@months) AS [months]
, abs(@days) AS [days]
, abs(@hours) AS [hours]
, abs(@minutes) AS [minutes]
, abs(@seconds) AS [seconds]
, abs(@milliseconds) AS [milliseconds]
答案 1 :(得分:2)
你得到这些负值,因为@dateFrom中的日期晚于@dateTo中的日期,我认为你可以做的最好的事情是在流程开始之前交换这些值,这样你就不需要重新格式化了过程后的变量:
DECLARE @auxDate DATETIME
IF (@dateFrom>@dateTo)
BEGIN
SET @auxDate = @dateFrom
SET @dateFrom = @dateTo
SET @dateTo = @auxDate
END
-- Your code..
答案 2 :(得分:0)
DECLARE @dateFrom DATETIME
DECLARE @dateTo DATETIME
DECLARE @tmpdate DATETIME
DECLARE @years INT
DECLARE @months INT
DECLARE @days INT
DECLARE @hours INT
DECLARE @minutes INT
DECLARE @seconds INT
DECLARE @milliseconds INT
DECLARE @sign CHAR
--SELECT @dateFrom = '2011-01-01 11:24:38:100'
--SELECT @dateTo = '2012-01-01 11:24:38:110'
SELECT @dateFrom = '2012-02-03 11:24:38:000'
SELECT @dateTo = '2013-03-04 12:25:39:003'
SELECT @sign = '+'
IF @dateFrom > @dateTo
BEGIN
SET @tmpdate = @dateFrom
SET @dateFrom = @dateTo
SET @dateTo = @tmpdate
SET @sign = '-'
END
SELECT @tmpdate = @dateFrom
SELECT @years = DATEDIFF(yy, @tmpdate, @dateTo)
- CASE WHEN
(DATEPART(mm, @dateFrom) > DATEPART(mm, @dateTo))
OR (DATEPART(mm, @dateFrom) = DATEPART(mm, @dateTo) AND DATEPART(dd, @dateFrom) > DATEPART(dd, @dateTo))
OR (DATEPART(dd, @dateFrom) = DATEPART(dd, @dateTo) AND DATEPART(hh, @dateFrom) > DATEPART(hh, @dateTo))
OR (DATEPART(hh, @dateFrom) = DATEPART(hh, @dateTo) AND DATEPART(mi, @dateFrom) > DATEPART(mi, @dateTo))
OR (DATEPART(mi, @dateFrom) = DATEPART(mi, @dateTo) AND DATEPART(ss, @dateFrom) > DATEPART(ss, @dateTo))
OR (DATEPART(ss, @dateFrom) = DATEPART(ss, @dateTo) AND DATEPART(ms, @dateFrom) > DATEPART(ms, @dateTo))
THEN 1
ELSE 0
END
SELECT @tmpdate = DATEADD(yy, @years, @tmpdate)
SELECT @months = DATEDIFF(mm, @tmpdate, @dateTo)
- CASE WHEN
(DATEPART(dd, @dateFrom) > DATEPART(dd, @dateTo))
OR (DATEPART(dd, @dateFrom) = DATEPART(dd, @dateTo) AND DATEPART(hh, @dateFrom) > DATEPART(hh, @dateTo))
OR (DATEPART(hh, @dateFrom) = DATEPART(hh, @dateTo) AND DATEPART(mi, @dateFrom) > DATEPART(mi, @dateTo))
OR (DATEPART(mi, @dateFrom) = DATEPART(mi, @dateTo) AND DATEPART(ss, @dateFrom) > DATEPART(ss, @dateTo))
OR (DATEPART(ss, @dateFrom) = DATEPART(ss, @dateTo) AND DATEPART(ms, @dateFrom) > DATEPART(ms, @dateTo))
THEN 1
ELSE 0
END
SELECT @tmpdate = DATEADD(mm, @months, @tmpdate)
SELECT @days = DATEDIFF(dd, @tmpdate, @dateTo)
- CASE WHEN
(DATEPART(hh, @dateFrom) > DATEPART(hh, @dateTo))
OR (DATEPART(hh, @dateFrom) = DATEPART(hh, @dateTo) AND DATEPART(mi, @dateFrom) > DATEPART(mi, @dateTo))
OR (DATEPART(mi, @dateFrom) = DATEPART(mi, @dateTo) AND DATEPART(ss, @dateFrom) > DATEPART(ss, @dateTo))
OR (DATEPART(ss, @dateFrom) = DATEPART(ss, @dateTo) AND DATEPART(ms, @dateFrom) > DATEPART(ms, @dateTo))
THEN 1
ELSE 0
END
SELECT @tmpdate = DATEADD(dd, @days, @tmpdate)
SELECT @hours = DATEDIFF(hh, @tmpdate, @dateTo)
- CASE WHEN
(DATEPART(mi, @dateFrom) > DATEPART(mi, @dateTo))
OR (DATEPART(mi, @dateFrom) = DATEPART(mi, @dateTo) AND DATEPART(ss, @dateFrom) > DATEPART(ss, @dateTo))
OR (DATEPART(ss, @dateFrom) = DATEPART(ss, @dateTo) AND DATEPART(ms, @dateFrom) > DATEPART(ms, @dateTo))
THEN 1
ELSE 0
END
SELECT @tmpdate = DATEADD(hh, @hours, @tmpdate)
SELECT @minutes = DATEDIFF(mi, @tmpdate, @dateTo)
- CASE WHEN
(DATEPART(ss, @dateFrom) > DATEPART(ss, @dateTo))
OR (DATEPART(ss, @dateFrom) = DATEPART(ss, @dateTo) AND DATEPART(ms, @dateFrom) > DATEPART(ms, @dateTo))
THEN 1
ELSE 0
END
SELECT @tmpdate = DATEADD(mi, @minutes, @tmpdate)
SELECT @seconds = DATEDIFF(ss, @tmpdate, @dateTo)
- CASE WHEN
(DATEPART(ms, @dateFrom) > DATEPART(ms, @dateTo))
THEN 1
ELSE 0
END
SELECT @tmpdate = DATEADD(ss, @seconds, @tmpdate)
SELECT @milliseconds = DATEDIFF(ms, @tmpdate, @dateTo)
SELECT
@sign AS [sign]
, @years AS [years]
, @months AS [months]
, @days AS [days]
, @hours AS [hours]
, @minutes AS [minutes]
, @seconds AS [seconds]
, @milliseconds AS [milliseconds]
答案 3 :(得分:0)
请查看我已回答Here的问题 它处理的案例如下:
@dateFrom ='2014-04-24 13:59:00'
@dateTo ='2014-04-24 14:01:00'
您的代码会为这些值返回错误的日期。
答案 4 :(得分:0)
CREATE FUNCTION CMN.UFN_AGE
( @DATE_BEG DATETIME,
@DATE_END DATETIME
) RETURNS NVARCHAR(255) AS
BEGIN
DECLARE @Ret NVARCHAR(255) = NULL;
DECLARE @s INT = DATEPART(SECOND, @DATE_END);
DECLARE @n INT = DATEPART(MINUTE, @DATE_END);
DECLARE @h INT = DATEPART(HOUR, @DATE_END);
DECLARE @d INT = DATEPART(DAY, @DATE_END);
DECLARE @m INT = DATEPART(MONTH, @DATE_END);
DECLARE @y INT = DATEPART(YEAR, @DATE_END);
IF (NOT ((@DATE_BEG IS NULL) OR (@DATE_END IS NULL)))
BEGIN
IF (@DATE_BEG < @DATE_END)
BEGIN
IF (@s < DATEPART(SECOND, @DATE_BEG))
BEGIN
SET @s = @s + 60;
SET @DATE_END = DATEADD(MINUTE,-1,@DATE_END);
SET @n = DATEPART(MINUTE, @DATE_END);
SET @h = DATEPART(HOUR, @DATE_END);
SET @d = DATEPART(DAY, @DATE_END);
SET @m = DATEPART(MONTH, @DATE_END);
SET @y = DATEPART(YEAR, @DATE_END);
END
IF (@n < DATEPART(MINUTE, @DATE_BEG))
BEGIN
SET @n = @n + 60;
SET @DATE_END = DATEADD(HOUR,-1,@DATE_END);
SET @h = DATEPART(HOUR, @DATE_END);
SET @d = DATEPART(DAY, @DATE_END);
SET @m = DATEPART(MONTH, @DATE_END);
SET @y = DATEPART(YEAR, @DATE_END);
END
IF (@h < DATEPART(HOUR, @DATE_BEG))
BEGIN
SET @h = @h + 24;
SET @DATE_END = DATEADD(DAY,-1,@DATE_END);
SET @d = DATEPART(DAY, @DATE_END);
SET @m = DATEPART(MONTH, @DATE_END);
SET @y = DATEPART(YEAR, @DATE_END);
END
SET @d = @d + DATEPART(DAY, EOMONTH(@DATE_BEG)) - DATEPART(DAY, @DATE_BEG);
IF (@d = DATEPART(DAY, EOMONTH(@DATE_BEG)))
BEGIN
SET @d = 0
END
ELSE IF (@d > DATEPART(DAY, EOMONTH(@DATE_BEG)))
BEGIN
SET @d = @d - DATEPART(DAY, EOMONTH(@DATE_BEG));
END
ELSE
BEGIN
SET @DATE_END = DATEADD(MONTH,-1,@DATE_END);
SET @m = DATEPART(MONTH, @DATE_END);
SET @y = DATEPART(YEAR, @DATE_END);
END
IF (@m < DATEPART(MONTH, @DATE_BEG))
BEGIN
SET @m = @m + 12;
SET @DATE_END = DATEADD(YEAR,-1,@DATE_END);
SET @y = DATEPART(YEAR, @DATE_END);
END
SET @s = @s - DATEPART(SECOND, @DATE_BEG);
SET @n = @n - DATEPART(MINUTE, @DATE_BEG);
SET @h = @h - DATEPART(HOUR, @DATE_BEG);
SET @m = @m - DATEPART(MONTH, @DATE_BEG);
SET @y = @y - DATEPART(YEAR, @DATE_BEG);
SET @Ret = CONCAT(CASE WHEN (@y < 1) THEN '' ELSE
CONCAT(FORMAT(@y, '00'), ' year(s) ') END,
CASE WHEN (@m < 1) THEN '' ELSE
CONCAT(FORMAT(@m, '00'), ' month(s) ') END,
CASE WHEN (@d < 1) THEN '' ELSE
CONCAT(FORMAT(@d, '00'), ' day(s) ') END,
FORMAT(@h, '00'), ':', FORMAT(@n, '00'), ':', FORMAT(@s, '00'));
END
END
RETURN @Ret;
END