Postgres使用generate_series搜索可用时隙

时间:2018-10-17 01:30:38

标签: postgresql gaps-and-islands

我的postgres数据库中有一个表,其中有一列日期。我想搜索缺少哪些日期-例如:

date
2016-11-09 18:30:00
2016-11-09 19:00:00
2016-11-09 20:15:00
2016-11-09 22:20:00
2016-11-09 23:00:00

在这里,|2016-11-09 21:00:00|丢失了。对生成的序列进行排序后,如果我的表在两个插槽(间隔为1小时的插槽)之间有一个条目,则需要删除该条目。

我想用generate_series进行查询,该查询向我返回缺少的日期。这可能吗?

我用来生成序列的样本查询。

    SELECT t
    FROM generate_series(
       TIMESTAMP WITH TIME ZONE '2016-11-09 18:00:00',
       TIMESTAMP WITH TIME ZONE '2016-11-09 23:00:00',
       INTERVAL '1 hour'
    ) t
    EXCEPT
    SELECT tscol
    FROM mytable;

但是此查询不能删除2016-11-09 18:30:00,2016-11-09 20:15:00等。因为我用过,除非。

1 个答案:

答案 0 :(得分:0)

这不是一个孤岛问题。您只想查找表中没有记录的1小时间隔。

EXCEPT在这里不起作用,因为它要进行相等比较,而您要检查记录是否存在 范围之内。

典型的解决方案是使用左连接反模式:

select dt
from generate_series(
    timestamp with time zone '2016-11-09 18:00:00',
    timestamp with time zone '2016-11-09 23:00:00',
    interval '1 hour'
) d(dt)
left join mytable t
    on t.tscol >= dt and t.tscol < dt + interval '1 hour'
where t.tscol is null

您也可以使用not exists

select dt
from generate_series(
    timestamp with time zone '2016-11-09 18:00:00',
    timestamp with time zone '2016-11-09 23:00:00',
    interval '1 hour'
) d(dt)
where not exists (
    select 1
    from mytable t
    where t.tscol >= dt and t.tscol < dt + interval '1 hour'
)

在此 demo on DB Fiddle 中,两个查询均返回:

| dt                     |
| :--------------------- |
| 2016-11-09 21:00:00+00 |