【问题标题】:How to sum UNIQUE total duarion in minutes from timestamp- sql如何从时间戳求和 UNIQUE 总持续时间(以分钟为单位)- sql
【发布时间】:2017-05-16 12:23:21
【问题描述】:

我有以下案例:

我的表有以下列:ID、ClientName(String)、StartTime(时间戳)、EndTime(时间戳)。

我的目标是总结每个客户的持续时间,例如最后一天,假设在一个时间段内可以有几个值,我必须只有真实的持续时间。

例如表格内容:

|Client1    |   2017-01-01 08:00:00      |   2017-01-01 08:05:00|
|Client1    |   2017-01-01 08:00:00      |   2017-01-01 08:10:00|

我在这个例子中使用了以下查询:

Select ClientName, SUM(date_trunc('second',coalesce(EndTime,now()::timestamp(0))-StartTime)) as duration 
from table 
group by ClientName

上述查询的结果是15,但应该是10。不应该计算同一时间段。

任何想法如何在 PostgreSQL 中获得正确的结果?

【问题讨论】:

  • MySQL 还是 SQL Server?
  • ... 还是 postgre?
  • @ZoharPeled 吹毛求疵:Use Postgres instead of Postgre
  • @wingedpanther 可以。
  • 根据您的样本数据,预期的输出是什么?

标签: postgresql timestamp postgresql-9.3


【解决方案1】:

您没有提及您使用的是哪个数据库,每个数据库的实现都不相同,但逻辑相同,

对于 Postgresql 我使用 row_number 删除不正确的行

    select ClientName,
           SUM(date_trunc('second',coalesce(EndTime,now()::timestamp(0))-StartTime)) as duration,
           SUM(datediff(minute,StartTime,EndTIme)) as Duration2
    from(
    select ClientName,
           StartTime,
           EndTIme,
           row_number () over ( partition by ClientName,StartTime order by EndTime desc) as rank
    from table) a
    where rank=1
    group by ClientName

【讨论】:

  • 我认为没有“错误”的行,只是重叠的行
  • 我正在使用 PostgreSQL。执行了你的例子,但它给了我错误:{{ ERROR: syntax error at or near "end"}}
  • 试试看,我加错结尾了
  • 谢谢,我检查了,现在出现语法错误:ERROR: syntax error at or near "table"
  • 输入你的表名,去掉别名
【解决方案2】:

从参考Calculate Actual Downtime ignoring overlap in dates/times试试这个

DECLARE @clientUsage TABLE (
    ID INT PRIMARY KEY NOT NULL IDENTITY(1,1),
    ClientName VARCHAR(25), 
    StartTime  DATETIME,
    EndTime  DATETIME
)

INSERT @clientUsage (ClientName, StartTime, EndTime) VALUES 
     ('client', '2014-11-20 17:31:01.467', '2014-11-20 18:01:01.243') 
    ,('client', '2014-11-28 17:59:00.987', '2014-11-28 18:09:02.167')
    ,('client', '2014-11-28 18:00:01.403', '2014-11-28 18:25:01.443') 
    ,('client', '2014-11-29 19:13:08.580', '2014-11-30 05:30:01.763') 
    ,('client', '2014-11-30 01:55:01.953', '2014-11-30 03:54:01.730')
    ,('client 2', '2014-12-19 23:09:01.303', '2014-12-22 09:43:01.397')
    ,('client 2', '2014-12-19 23:09:01.303', '2014-12-22 09:43:01.397')
    ,('client 2', '2014-12-19 23:09:01.303', '2014-12-22 09:43:01.397') 
    ,('client 2', '2014-12-19 23:09:01.303', '2014-12-22 09:43:01.397')
    ,('client 2', '2014-12-19 23:09:01.303', '2014-12-22 09:43:01.397') 

如果你使用你的表而不是临时表

select clientname,sum(actual) from
(SELECT
    clienttime.ClientName,
    clienttime.StartTime,
    clienttime.EndTime,
    COALESCE(Actual, 0) AS Actual
FROM @clientUsage clienttime
    LEFT OUTER JOIN (
        SELECT DISTINCT
            D1.ClientName,
            MIN(CASE WHEN D1.StartTime < D2.StartTime THEN D1.ID ELSE D2.ID END) AS [ID],
            MIN(CASE WHEN D1.StartTime < D2.StartTime THEN D1.StartTime ELSE D2.StartTime END) AS [StartTime],
            MAX(CASE WHEN D1.EndTime > D2.EndTime THEN D1.EndTime ELSE D2.EndTime END) AS [EndTime],
            DATEDIFF(MINUTE,
                MIN(CASE WHEN D1.StartTime < D2.StartTime THEN D1.StartTime ELSE D2.StartTime END),
                MAX(CASE WHEN D1.EndTime > D2.EndTime THEN D1.EndTime ELSE D2.EndTime END)) AS Actual
        FROM @clientUsage D1
            INNER JOIN @clientUsage D2
                ON D1.ClientName = D2.ClientName
                    AND (D1.StartTime BETWEEN D2.StartTime AND D2.EndTime
                        OR D2.StartTime BETWEEN D1.StartTime AND D1.EndTime)
        GROUP BY
            D1.ClientName,
            D1.StartTime
    ) Outages
        ON Outages.ID = clienttime.ID) op group by clientname

我在sql server中测试过。

【讨论】:

    猜你喜欢
    • 2014-02-27
    • 2014-07-11
    • 2013-10-11
    • 2012-08-21
    • 1970-01-01
    • 2011-07-18
    • 2021-12-12
    • 2017-03-25
    • 1970-01-01
    相关资源
    最近更新 更多