【问题标题】:Sum datetime durations between start and end开始和结束之间的日期时间总和
【发布时间】:2018-01-29 19:47:43
【问题描述】:

我有一个表,它使用开始和结束日期时间列跟踪整数状态变量。当监控的状态变量发生变化时,另一个程序会更新表。它将最后一个条目的 end_timestamp 设置为当前时间,并插入一个以当前时间为 start_timestamp 的新状态行。这样做的结果是当前经过的状态持续时间的 end_timestamp 为 Null。

它的外观如下:

我正在尝试找到在给定的开始和结束日期时间之间查询每个状态持续时间的最佳方法,以秒为单位。将完全落在提供的端点内的状态持续时间相加是微不足道的,但我不确定处理边缘的最佳方法。我之前已经在数据库之外完成了这项工作,通过查找最新开始和最早结束,获取差异并增加总和。

这是我当前对求和持续时间的查询,包括当前经过的查询:

SELECT status, sum(datediff(S, start_timestamp, ISNULL([end_timestamp], GETDATE()))) as duration
FROM [status_table]
WHERE start_timestamp >= @start AND
(end_timestamp <= @end OR end_timestamp is Null)
GROUP BY status;

示例结果:

视觉参考:

【问题讨论】:

  • 如果一个时段在另一个结束之前开始并且在另一个开始之后结束,则两个时段重叠。 start &lt; @end AND (end IS NULL OR end &gt; @start)
  • 你也应该不使用GETDATE(),而是看起来你应该使用ISNULL(end, @end)
  • @MatBailie 好点,当我需要持续状态时,我可以将当​​前时间戳作为查询中的端点传递。谢谢!

标签: sql sql-server tsql datetime datediff


【解决方案1】:

只需将 case 语句添加到您的 SUM 中,并确保您的 where 检查开始日期和结束日期在 BETWEEN 之间

select  [status],
        sum(datediff(
            second, 
            case when start_timestamp < @start then @start else start_timestamp end, 
            case when end_timestamp is null or end_timestamp > @end then @end else end_timestamp end
            )
        ) as duration
from    status_table
where   (@start <= isnull(end_timestamp,@end))
and     (end_timestamp IS NULL or @end  >= end_timestamp)
group by [status]

更新

尝试保持查询可搜索

select      [status],
            sum(datediff(second, startdt, enddt)) as duration
from        (
                select      [status],   
                            case when start_timestamp < @start then @start else start_timestamp end as startdt,
                            case when end_timestamp is null or end_timestamp > @end then @end else end_timestamp end as enddt
                from        status_table
                where       (start_timestamp < @end)
                and         (end_timestamp is null or end_timestamp > @start)
) t
group by    [status]

【讨论】:

  • 您的 where 子句可以简化。如果你有@a &lt;= X OR @a BETWEEN X AND Y,那么你实际上只有@a &lt;= Y
  • @MatBailie 有道理.. 让我看看结尾和
  • 你也复制了OP对GETDATE()的使用,但是根据OP自己的描述,代理端应该只是@end
  • @MatBailie 是正确的,我得到了 OPs 查询按预期工作的那几处更改。谢谢大家!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多