Sql Postgres检查表行中的时间戳范围重叠

Sql Postgres检查表行中的时间戳范围重叠,sql,postgresql,datetime,time-series,Sql,Postgresql,Datetime,Time Series,我们有一个Postgres表物化视图,其中包含大约200万行,列如下: 开始时间timestampz-具有索引 结束时间timestampz-has索引 对于表中的每一行,我们希望添加一个结果列,其中包含: 1,如果行开始和结束时间范围与任何其他行重叠 0,如果行开始和结束时间范围不与任何其他行重叠 将每一行标记为重叠1或重叠0的有效方法是什么 编辑: 预期输出如下所示: 行id 具有重叠-布尔值或整数1或0 我不认为会有一个真正快速的解决方案,因为它需要将表中的每一行与表中的每一行或至少与指定

我们有一个Postgres表物化视图,其中包含大约200万行,列如下:

开始时间timestampz-具有索引 结束时间timestampz-has索引 对于表中的每一行,我们希望添加一个结果列,其中包含:

1,如果行开始和结束时间范围与任何其他行重叠 0,如果行开始和结束时间范围不与任何其他行重叠 将每一行标记为重叠1或重叠0的有效方法是什么

编辑:

预期输出如下所示:

行id 具有重叠-布尔值或整数1或0
我不认为会有一个真正快速的解决方案,因为它需要将表中的每一行与表中的每一行或至少与指定范围内的每一行进行比较

假设表的主键列名为id,则可以使用Postgres的range函数检查重叠行:

with check_period (check_range) as (
   values ( tstzrange(timestamptz '2018-10-01 00:00:00', timestamptz '2018-10-14 20:15:00') )
)
select id, 
       start_Time, 
       end_time, 
       exists (select *
        from the_table t2
           cross join check_perioud
        where t2.id <> t1.id 
        and tstzrange(t1.start_time, t1.end_time) && tstzrange(t2.start_time, t2.start_time)
        and tstzrange(t2.start_time, t2.start_time) <@ check_range
       ) has_overlapping_rows
from the_table t1
  cross join check_period
where tstzrange(t1.start_time, t1.end_time) <@ check_range;
您应该在时间戳范围上创建一个索引,以便快速:

create index on the_table( (tstzrange(start_time, end_time), id );
您可以扩展上述查询以返回重叠行的计数,而不是true/false标志:

select id, 
       start_Time, 
       end_time, 
       (select count(*)
        from the_table t2
        where t2.id <> t1.id 
        and tstzrange(t1.start_time, t1.end_time) && tstzrange(t2.start_time, t2.start_time)
        and tstzrange(t2.start_time, t2.start_time) <@ tstzrange(timestamptz '2018-10-01 00:00:00', timestamptz '2018-10-14 20:15:00')
       ) has_overlapping_rows
from the_table t1
where tstzrange(t1.start_time, t1.end_time) <@ tstzrange(timestamptz '2018-10-01 00:00:00', timestamptz '2018-10-14 20:15:00');

但是,对于有许多重叠行的行,这将更慢,因为count*强制数据库检查所有重叠行。exists解决方案可以在找到的第一行停止。

我们找到的最接近的答案是:但是,它只返回重叠的行。我们特别需要计算重叠的数量,并将这些计数用于后续的报告/异常值分析。此外,如果您提出的查询有点慢,也可以,因为我们将具体化结果。通过这种方式,数据是预先计算的,例如在夜间。对tstzrange指数的极好建议!在第二个例子中,没有CTE,第二个and语句做什么?我们不想硬编码任何日期范围,是否也应该删除它?@bryliechristopherxley:如果没有CTE,您必须在要分析的时段上重复条件,除非您想比较时段中的所有行以与所有其他行进行检查,也就是说,如果这些行有任何重叠行,即使在要检查的时间段之外,顺便说一句:CTE的查询中也有相同的条件
select id, 
       start_Time, 
       end_time, 
       (select count(*)
        from the_table t2
        where t2.id <> t1.id 
        and tstzrange(t1.start_time, t1.end_time) && tstzrange(t2.start_time, t2.start_time)
        and tstzrange(t2.start_time, t2.start_time) <@ tstzrange(timestamptz '2018-10-01 00:00:00', timestamptz '2018-10-14 20:15:00')
       ) has_overlapping_rows
from the_table t1
where tstzrange(t1.start_time, t1.end_time) <@ tstzrange(timestamptz '2018-10-01 00:00:00', timestamptz '2018-10-14 20:15:00');