我在 Redshift 数据库中有一个表,其中包含分组且可能重叠的间隔,如下所示:
| interval_id | l | u | group |
| ----------- | -- | -- | ----- |
| 1 | 1 | 10 | A |
| 2 | 2 | 5 | A |
| 3 | 5 | 15 | A |
| 4 | 26 | 30 | B |
| 5 | 28 | 35 | B |
| 6 | 30 | 31 | B |
| 7 | 44 | 45 | B |
| 8 | 56 | 58 | C |
我想做的是确定组内间隔的并集长度。也就是说,对于每个间隔,取 u - l
,对所有组成员求和,然后减去间隔之间重叠的长度。
期望的结果:
| group | length |
| ----- | ------ |
| A | 14 |
| B | 10 |
| C | 2 |
这个问题has been asked before可惜该线程中的所有解决方案似乎都使用了 Redshift 不支持的功能。
最佳答案
这并不困难,但需要多个步骤。关键是定义每个组内的“岛屿”,然后对这些“岛屿”进行聚合。许多子查询、聚合和窗口函数。
select groupId, sum(ul)
from (select groupId, (max(u) - min(l) + 1) as ul
from (select t.*,
sum(case when prev_max_u < l then 1 else 0 end) over (order by l) as grp
from (select t.*,
max(u) over (order by l rows between unbounded preceding and 1 preceding) as prev_max_u
from t
) t
) t
group by groupid, grp
) g
group by groupId;
这个想法是确定每个记录的开头是否存在重叠。为此,它对所有先前记录使用累积最大值函数。然后,它通过将之前的最大值与当前的 l
进行比较来确定是否存在重叠——重叠的累积和定义了一个组。
剩下的只是聚合。还有更多聚合。
关于sql - 重叠区间的总长度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42636540/