【问题标题】:PostgreSQL unnest, int4range with where clausePostgreSQL unnest, int4range with where 子句
【发布时间】:2020-04-28 13:56:39
【问题描述】:

我有一个名为 mytable 的数据表:

╔════╤══════════════════════════════╤══════════╗
║ id │ segments                     │ duration ║
╠════╪══════════════════════════════╪══════════╣
║ 1  │ {"[1,4)","[6,13)","[15,19)"} │ 14       ║
╟────┼──────────────────────────────┼──────────╢
║ 2  │ {"[3,16)","[19,22)"}         │ 16       ║
╚════╧══════════════════════════════╧══════════╝

segments 是以秒为单位的时间间隔数组。
duration 是以秒为单位的segments 时间间隔的总和。

例如,对于id=1,segments 中的三个时间间隔分别为 3、7 和 4 秒。它们在duration 中总共需要 14 秒。

我想从这个表中只提取满足这两个条件的行:

  • 没有个人segments不少于10秒
  • duration 至少为 10 秒

查询应该只返回id=1,因为它的每个segments 都小于10 秒,并且它的duration 至少是10 秒。

查询不应返回id=2,因为其中一个segments 的长度为13 秒。它的duration 至少为 10 秒,但它不符合关于segments 的第一个条件。

【问题讨论】:

  • 您存储的是字符串数组还是嵌套的数字数组?我不清楚您对数据的表示。
  • 数字的嵌套数组。数据类型为 int4range。

标签: sql arrays postgresql unnest


【解决方案1】:

在横向连接中取消嵌套数组并按id 分组计算总和。使用布尔聚合 bool_and() 来消除少于 10 秒的段。

select id, segments, sum(elem.upper- elem.lower) as duration
from my_table
cross join unnest(segments) elem
group by id
having bool_and(elem.upper- elem.lower < 10)
and sum(elem.upper- elem.lower) >= 10

Db<>Fiddle.

【讨论】:

    【解决方案2】:

    您可以进行横向连接:

    select t.*
    from mytable t
    inner join lateral (
        select bool_and(seg.upper - seg.lower < 10) to_keep
        from unnest(t.segments) seg 
    ) x on x.to_keep
    where t.duration >+ 10
    

    子查询将数组取消嵌套,并使用bool_or() 确保所有间隔小于10 秒;连接条件消除了不需要的行。

    Demo on DB Fiddle

    编号 |段 |期间 -: | :---------------------------- | --------: 1 | {"[1,4)","[6,13)","[15,19)"} | 14

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-16
      • 1970-01-01
      • 2018-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多