使用 SQL 中的两个时间戳列在 "point-in_time" 处生成计数

Using two timestamp columns in SQL to generate counts at a "point-in_time"

我有一个带有票证的 Postgres 数据库 table。每张票都有一个 'created_at' 时间戳和一个 'resolved_at' 时间戳。我最终想创建一个时间序列可视化来跟踪一段时间内 'unresolved' 票的数量。

例如,我想查看过去 24 小时,看看每个小时结束时有多少工单未解决,即 created_at < "point-in-time" AND resolved_at > "point-in-time".

我不知道我是如何开始查询这类信息的。我如何在查询中引用多个 "point-in-time values"?

示例设置:

CREATE TABLE tickets (
    id int,
    created_at timestamp,
    resolved_at timestamp
);

INSERT INTO tickets VALUES
(1, '2019-10-01 01:30:00'::timestamp, '2019-10-01 05:45:00'::timestamp),
(2, '2019-10-01 02:30:00'::timestamp, '2019-10-01 05:45:00'::timestamp),
(3, '2019-10-01 03:30:00'::timestamp, '2019-10-01 05:45:00'::timestamp),
(4, '2019-10-01 04:30:00'::timestamp, '2019-10-01 05:45:00'::timestamp),
(5, '2019-10-01 05:30:00'::timestamp, '2019-10-01 05:45:00'::timestamp);

我可以从这些数据中看出,在 01:00 我们有 0 个未解决,在 02:00 1 个未解决(票 1),...,05:00 4 个未解决, 06:00 0 未解决(所有工单已由 05:45 解决)。我不确定如何查询此信息

我们将分三个逻辑步骤找到解决方案。一、及时获取一系列事件:

select created_at as event_time, 1 as change
from tickets
union all
select resolved_at, -1
from tickets
order by 1

     event_time      | change 
---------------------+--------
 2019-10-01 01:30:00 |      1
 2019-10-01 02:30:00 |      1
 2019-10-01 03:30:00 |      1
 2019-10-01 04:30:00 |      1
 2019-10-01 05:30:00 |      1
 2019-10-01 05:45:00 |     -1
 2019-10-01 05:45:00 |     -1
 2019-10-01 05:45:00 |     -1
 2019-10-01 05:45:00 |     -1
 2019-10-01 05:45:00 |     -1
(10 rows)

接下来,将时间四舍五入为整小时并对变化求和:

select 
    date_trunc('hour', event_time+ interval '1h') as time_point, 
    sum(change) as change
from (
    select created_at as event_time, 1 as change
    from tickets
    union all
    select resolved_at, -1
    from tickets
    ) s
group by 1
order by 1

     time_point      | change 
---------------------+--------
 2019-10-01 02:00:00 |      1
 2019-10-01 03:00:00 |      1
 2019-10-01 04:00:00 |      1
 2019-10-01 05:00:00 |      1
 2019-10-01 06:00:00 |     -4
(5 rows)

最后得到连续周期变化的累计和:

select 
    time_point, 
    sum(change) over (order by time_point) as unresolved
from (
    select
        date_trunc('hour', event_time+ interval '1h') as time_point, 
        sum(change) as change
    from (
        select created_at as event_time, 1 as change
        from tickets
        union all
        select resolved_at, -1
        from tickets
        ) s
    group by 1
    ) s 
order by 1

     time_point      | unresolved 
---------------------+------------
 2019-10-01 02:00:00 |          1
 2019-10-01 03:00:00 |          2
 2019-10-01 04:00:00 |          3
 2019-10-01 05:00:00 |          4
 2019-10-01 06:00:00 |          0
(5 rows)

在最终查询中,您可以使用时间戳系列(由函数生成)来避免间隙:

select 
    time_point, 
    coalesce(sum(change) over (order by time_point), 0) as unresolved
from 
    generate_series(timestamp '2019-10-01 01:00', '2019-10-01 06:00', interval '1h') as time_point
left join (
    select
        date_trunc('hour', event_time+ interval '1h') as time_point, 
        sum(change) as change
    from (
        select created_at as event_time, 1 as change
        from tickets
        union all
        select resolved_at, -1
        from tickets
        ) s
    group by 1
    ) s using(time_point)
order by 1