Bry*_*ley 4 sql postgresql datetime time-series
我们有一个 Postgres 表(物化视图),其中包含大约 200 万行,其中的列如下:
对于表中的每一行,我们想添加一个结果列,其中包含:
将每一行标记为具有重叠(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;
Run Code Online (Sandbox Code Playgroud)
该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');
Run Code Online (Sandbox Code Playgroud)
您应该在时间戳范围上创建一个索引以使其快速:
create index on the_table( (tstzrange(start_time, end_time), id );
Run Code Online (Sandbox Code Playgroud)
您可以扩展上述查询以返回重叠行的计数而不是真/假标志:
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');
Run Code Online (Sandbox Code Playgroud)
但是,对于具有许多重叠行的行,这会更慢,因为这会count(*)强制数据库检查所有重叠行。该exists()解决方案可以在第一排FOUND停止。