PostgreSQL unnest,带有where子句的int4range

时间:2020-01-10 22:23:30

标签: sql arrays postgresql unnest

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

mytable

╔════╤══════════════════════════════╤══════════╗ ║ id │ segments │ duration ║ ╠════╪══════════════════════════════╪══════════╣ ║ 1 │ {"[1,4)","[6,13)","[15,19)"} │ 14 ║ ╟────┼──────────────────────────────┼──────────╢ ║ 2 │ {"[3,16)","[19,22)"} │ 16 ║ ╚════╧══════════════════════════════╧══════════╝ 是一个以秒为单位的时间间隔数组。
segmentsduration中时间间隔的总和,以秒为单位。

例如,对于segments = 1,id中的三个间隔分别为3、7和4秒。他们在segments中总共花费了14秒。

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

  • 没有单个duration的时长不少于10秒
  • 具有至少10秒的segments

查询仅应返回duration = 1,因为其各个id小于10秒,而其segments至少为10秒。

该查询不应返回duration = 2,因为其id之一长度为13秒。它的segments至少有10秒,但它没有涉及duration的第一个条件。

2 个答案:

答案 0 :(得分: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.

答案 1 :(得分:1)

您可以进行横向连接:

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

id | segments                     | duration
-: | :--------------------------- | -------:
 1 | {"[1,4)","[6,13)","[15,19)"} |       14
相关问题