当前位置: 首页 > 知识库问答 >
问题:

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

松越
2023-03-14

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

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

对于表中的每一行,我们希望添加一个包含以下内容的结果列:

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

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

编辑:

预期产出大致如下:

  • row_id
  • has_overlap-布尔或int(1或0)

共有1个答案

滑畅
2023-03-14

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

假设表的主键列名为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;

CTEcheck_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 );

您可以扩展上述查询以返回重叠行的计数,而不是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');

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

 类似资料:
  • 我有一个dynamodb表,其结构如下 我想在此表上执行两个主要查询。 获取用户的所有条目- 还有其他建议吗?谢谢你。 2014年5月更新这里发布了一些很好的建议。我仍在尝试如何最好地实现这一点,并希望检查以下方法的优缺点。 我担心这可能会造成很多不一致,好像对usertrips或recenttrips的插入失败了等等。

  • 问题内容: 我在PostgreSQL 9.2中有一张表,看起来像这样(简化): 对于每个feature_id,可能会有多行,其时间范围由begin_time / end_time指定。它们可能重叠,但这是相对罕见的。我正在寻找一种快速的方法来查找所有具有/不具有 任何 重叠的feature_id 。 我尝试使用窗口函数来执行此操作,如下所示: …但这是行不通的: 该算法很简单:按begin_tim

  • 问题内容: 我有一个元组列表,每个元组都是一个。我正在尝试合并所有重叠的时间范围,并返回不同时间范围的列表。例如 这是我的实现方法。 我想弄清楚是否 是某些python模块中的内置函数可以更有效地做到这一点吗?要么 有没有达到相同目标的更Python方式? 感谢您的帮助。谢谢! 问题答案: 使用Pythonic可以提高效率的几种方法: 消除了构造,因为该算法应在主循环中删除重复项。 如果只需要遍历

  • 我需要在一定的时间范围内进行查询, 首先,我想做一个查询,比如 结果是 有人能指出我做错了什么吗? 第二,我没有做这个例子https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-daterange-aggregation.html 上面的例子如何适合我的应用,谢谢 杰夫 此

  • 问题内容: 该表用于存储会话(事件): 我们不想在范围之间产生冲突。 假设我们需要在 2010-01-05 至 2010-01-25之间 插入一个新会话。 我们想知道有冲突的会话。 这是我的查询: 结果如下: 有没有更好的方法来做到这一点? 小提琴 问题答案: 我曾经用日历应用程序进行过这样的查询。我想我使用了这样的东西: 更新 这肯定应该工作((ns,ne,es,ee)=(new_start,n

  • 问题内容: 我正在使用Joda Time 2.1库。 我已经编写了一种比较给定日期是否在日期范围之间的方法。我希望它包含开始日期和结束日期。我已经习惯了,因为我不想考虑时间部分仅是日期部分。 下面是它的代码。 上面方法的输出是: 我的问题是错误的,即使日期和具有相同的值。 我想要那个,但这里只考虑。 我希望它具有包容性。 这是否意味着该方法专门找到一个匹配项? 我在Joda Time中浏览了Jav