开始和结束之间的日期时间总和

时间:2018-01-29 19:47:43

标签: sql sql-server tsql datetime datediff

我有一个表,它跟踪一个包含start和end datetime列的整数状态变量。当其监视的状态变量发生变化时,另一个程序会更新该表。它将最后一个条目的end_timestamp设置为当前时间,并插入一个新的状态行,其中当前时间为start_timestamp。这样做的结果是当前经过的状态持续时间的end_timestamp为Null。

以下是它的外观:

Here's how it looks.

我试图找到查询给定开始日期和结束日期时间之间每个状态持续时间(以秒为单位)的最佳方法。总结在提供的端点内干净地落下的状态持续时间是微不足道的,但我不确定处理边缘的最佳方法。我以前在数据库之外完成了这项任务,通过查找最新开始和最早结束,获得差异并增加总和。

这是我目前对求和持续时间的查询,包括当前流逝的持续时间:

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;

示例结果:

Sample result.

视觉参考:

Visual reference

1 个答案:

答案 0 :(得分:1)

只需在SUM中添加一个case语句,并确保在哪里检查开始和结束日期是否为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]

<强>更新

尝试保持查询sargable

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]