gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-29 12:35:01 25 4
gpt4 key购买 nike

我们有一个 Postgres 表(物化 View ),其中包含大约 200 万行,其中的列如下:

  • start_time (timestampz) - 有索引
  • end_time (timestampz) - 有索引

对于表中的每一行,我们要添加一个结果列,其中包含:

  • 1,如果行开始和结束时间范围与任何其他行重叠
  • 0,如果行开始和结束时间范围不与任何其他行重叠

将每一行标记为重叠(1 或 0)的有效方法是什么?

编辑:

预期的输出是这样的:

  • 行号
  • has_overlap - bool 值或整数(1 或 0)

最佳答案

我认为不会有真正快速的解决方案,因为它确实需要将表中的每一行与表中的每一行(或至少指定范围内的每一行)进行比较。

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

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;

CTE check_period 只是在那里,因此您要分析的时间段的值不会重复。如果您不介意重复它们,可以将其删除:

select id, 
start_Time,
end_time,
exists (select *
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');

您应该在时间戳范围内创建一个索引以加快速度:

create index on the_table( (tstzrange(start_time, end_time), id );

您可以扩展上述查询以返回重叠行的计数而不是真/假标志:

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() 解决方案可以在找到第一行时停止。

关于sql - Postgres 检查表行中的时间戳范围重叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52812212/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com