Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 超过24小时的总日期时间_Sql_Sql Server - Fatal编程技术网

Sql 超过24小时的总日期时间

Sql 超过24小时的总日期时间,sql,sql-server,Sql,Sql Server,有没有办法把datetime加起来,总数就超过24小时 这是我的脚本,通话时间存储为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(

有没有办法把datetime加起来,总数就超过24小时

这是我的脚本,通话时间存储为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只能在datetime上存储24小时。是否有一种变通方法可用于获得所需的输出?

将持续时间存储在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
结果


如果您只是想得到两个日期时间值之间的持续时间,可以使用简单的
DATEDIFF
计算。这是一种相当冗长的方法,如果要使用它,您最好在函数中修改并保留它:

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))
| COLUMN_0 |
|----------|
| 42:37:58 |
分隔时间段并返回字符串表示形式

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))
| COLUMN_0 |
|----------|
| 42:37:58 |

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))
| COLUMN_0 |
|----------|
| 42:37:58 |

您需要将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;
此处的格式设置执行以下操作:

  • 将秒转换为
    DATETIME
    -
    DATEADD(秒,秒,0),108)
  • 将此日期时间转换为
    VARCHAR
    ,格式为
    hh:mm:ss
    -
    Convert(VARCHAR(8),[DATETIME]),108)
  • 将经过的小时数计算为
    VARCHAR
    -
    CAST(地板(秒/3600)为VARCHAR(5))
  • 使用
    STUFF
    将这些小时以
    hh:mm:ss
    的格式插入字符串中,以代替
    hh
  • 我在评论中建议您将持续时间存储为整数的原因是,为了做任何有用的事情,您需要将其转换为整数,因此您可以省去中间人,避免每次需要使用值时都将varchar转换为time,然后将time转换为整数

    如果无法更改表结构,您可以在表中添加计算列以简化计算,例如

    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
        );
    
    我使用内联表值函数纯粹是出于性能原因

    尝试以下方法:

    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
    

    用表1替换最后2个示例行

    日期值的格式和类型是什么?那么,您希望您的输出是什么?您能提供一些示例数据和所需的输出吗?对于持续时间来说,时间或日期时间不是一个好的选择。持续时间应存储为十进制/整数,例如,不存储
    hh:mm:ss
    ,只存储经过的秒数。所以
    01:02:03
    变成了
    3723
    。如果您想在演示层中以
    hh:mm:ss
    格式显示3723,请担心这个问题。@garethdate-time是存储持续时间的好方法,您可以正常添加它们,并在不计算的情况下请求不同的部分。Duration=enddatetime-startdatetime,但不能在上直接使用聚合datetimes@t-克劳森:不是。您如何将25小时30分钟存储为约会时间?如果开始时间是相关的,我同意如果开始时间是相关的,那么将开始和结束日期存储为日期时间是最好的方法,但是对于任意的持续时间,它应该是decimal/int.Hi。我要做的是添加datetime字段。结果将超过24小时。@ElishTorres这里有一个更新的答案,其中有一些相当丑陋的计算,可能会帮助你我自己明白了我要做什么。无论如何,谢谢。:)这是MsSQL。我犯了个错误“秒到秒时间”不是可识别的函数名TIME_TO_SEC'不是一个可识别的函数名。对不起,我将您的评论误读为“对不起,这是MySQL”,而不是“MsSQL”-我会编辑我自己知道我在做什么。无论如何,谢谢。:)