如何使用年,月,日,小时,分钟,秒和毫秒计算T-SQL中的年龄

时间:2012-06-25 06:38:13

标签: sql sql-server

此问题是问题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

帮助将不胜感激!

5 个答案:

答案 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