和日期时间超过24小时

时间:2015-01-19 10:01:35

标签: sql sql-server

有没有办法可以添加日期时间,总和将超过24小时?

这是我的脚本,talkTime存储为varchar。

select 
cast(sum(cast(left(right(convert(char(19),cast(talkTime as datetime),120),8),2) as int)+
(cast(left(right(convert(char(19),cast(talkTime as datetime),120),5),2) as real)/60)+
(cast(left(right(convert(char(19),cast(talkTime as datetime),120),2),2) as real)/3600)) as datetime)
from table1

这是我试图总结的数据。

talkTime
0:45:43
4:19:42
4:21:19
5:52:29
4:59:25
6:06:21
5:03:00
5:51:24
5:18:35

总数应该是。 42:37:58。但相反,我得到的就是这个。 1900-02-12 15:11:12.047。我读过这是因为sql只能在24小时存储日期时间。有什么工作可以用来获得我想要的输出吗?

4 个答案:

答案 0 :(得分:1)

如果您只想查看2个日期时间值之间的持续时间,则可以使用简单的DATEDIFF计算。这是一个相当漫长的方法,如果您要使用它,理想情况下您可以修改并保留在函数中:

SQL Fiddle Demo

MS SQL Server架构设置

CREATE TABLE TalkTime
    ([talkTime] time(4))
;

INSERT INTO TalkTime
    ([talkTime])
VALUES
    ('0:45:43'),
    ('4:19:42'),
    ('4:21:19'),
    ('5:52:29'),
    ('4:59:25'),
    ('6:06:21'),
    ('5:03:00'),
    ('5:51:24'),
    ('5:18:35')
;

分隔时间段并返回字符串表示

DECLARE @hours INT
DECLARE @mins INT
DECLARE @secs INT

SELECT @hours = SUM(DATEDIFF(HOUR, '0:00:00', talktime)) +
((SUM(DATEDIFF(minute, '0:00:00', talktime)) - (SUM(DATEDIFF(hour, '0:00:00', talktime)) *60)) / 60)
FROM TalkTime

SELECT @mins = (SUM(DATEDIFF(SECOND, '0:00:00', talktime)) - (@hours*60*60))/60
FROM TalkTime

SELECT @secs = (SUM(DATEDIFF(SECOND, '0:00:00', talktime))) - ((@hours*60*60) + (@mins*60))
FROM    TalkTime

SELECT CAST(@hours AS NVARCHAR(4)) + ':' + CAST(@mins AS NVARCHAR(2)) + ':' +  CAST(@secs AS NVARCHAR(2))

<强> Results

| COLUMN_0 |
|----------|
| 42:37:58 |

答案 1 :(得分:1)

试试这个:

SELECT
  cast(datediff(hour, 0, 
    dateadd(s, sum(datediff(second, 0, talktime)), 0)) as varchar(5))
  + right(convert(char(19),dateadd(s, sum(datediff(second, 0, talktime)),0), 126), 6)
FROM 
  (values(cast('12:55:02' as time)),
    (cast('13:55' as time))) table1(talktime)

结果:

26:50:02

用table1

替换最后2个示例行

答案 2 :(得分:0)

使用

时,将持续时间存储在datetime中,但将DATEDIFF()存储为'1900-01-01'
DECLARE @StartTime datetime = '2015-01-19 17:18', @EndTime datetime = GETDATE()

SELECT 
    @StartTime AS StartTime,
    @EndTime AS EndTime,
    @EndTime - @StartTime AS Duration,
    DATEDIFF(DAY, '1900-01-01', @EndTime - @StartTime) AS Day, 
    DATEDIFF(HOUR, '1900-01-01', @EndTime - @StartTime) % 24 AS Hour, 
    DATEDIFF(MINUTE, '1900-01-01', @EndTime - @StartTime) % 60 AS Minute, 
    DATEDIFF(SECOND, '1900-01-01', @EndTime - @StartTime) % 60 AS Second, 
    RIGHT(CONVERT(varchar(20), @EndTime - @StartTime, 120), 8) AS Time

结果

Result

答案 3 :(得分:0)

您需要将varchar转换为时间,然后使用DATEDIFF将时间转换为秒,然后才能总结:

SELECT Seconds = SUM(DATEDIFF(SECOND, '00:00', CAST(Duration AS TIME)))
FROM T;

然后,您可以使用各种转化将结果返回到VARCHAR,不过我最好建议您在表示层中进行此转换:

CREATE TABLE #T (Duration varchar(7));
INSERT INTO #T (Duration)
VALUES
    ('0:45:43'), ('4:19:42'), ('4:21:19'), ('5:52:29'), ('4:59:25'),
    ('6:06:21'), ('5:03:00'), ('5:51:24'), ('5:18:35');

SELECT  Formatted = STUFF(CONVERT(VARCHAR(8), DATEADD(SECOND, Seconds, 0), 108), 
                            1, 2, CAST(FLOOR(Seconds / 3600) AS VARCHAR(5)))
FROM (  SELECT Seconds = SUM(DATEDIFF(SECOND, '00:00', CAST(Duration AS TIME)))
        FROM #T
    ) AS s;

此处的格式化执行以下操作:

  1. 将秒数转换为DATETIME - DATEADD(SECOND, Seconds, 0), 108)
  2. 将此DATETIME转换为格式为VARCHAR - hh:mm:ss的{​​{1}}。
  3. CONVERT(VARCHAR(8), [Datetime]), 108) - VARCHAR
  4. 计算经过的小时数
  5. 使用CAST(FLOOR(Seconds / 3600) AS VARCHAR(5))
  6. hh:mm:ss格式代替hh将这些小时数插入字符串

    我在评论中建议您将持续时间存储为整数的原因是因为这是您需要将其转换为无论如何要做任何有用的事情,所以你不妨切断中间人并避免必须将varchar转换为时间,然后每次需要使用值时将时间转换为整数。

    如果您无法更改表格结构,则可以在表格中添加计算列,以便更轻松地进行计算,例如。

    STUFF

    您可以将格式化逻辑放在自己的函数中:

    ALTER TABLE T ADD DurationInSeconds AS DATEDIFF(SECOND, '00:00', CAST(Duration AS TIME));
    

    然后您的查询就像:

    一样简单
    CREATE FUNCTION [dbo].[GetFormattedDuration] (@Second DECIMAL(15, 2))
    RETURNS TABLE
    AS
        RETURN 
        (
            SELECT  FormattedDuration = CASE WHEN @Second < 86400 THEN CONVERT(VARCHAR(8), DATEADD(MILLISECOND, (@second  * 1000), '00:00:00.000'), 108)
                                            ELSE STUFF(CONVERT(VARCHAR(8), DATEADD(MILLISECOND, (@second  * 1000), '00:00:00.000'), 108), 1, 2, CAST(FLOOR(@Second / 3600) AS VARCHAR(5)))
                                        END
        );
    

    我纯粹出于性能原因使用了内联表值函数