我在PostgreSQL 9.2中有一个表,看起来像这样(简化):
CREATE TABLE my_features
(
id integer NOT NULL,
feature_id integer NOT NULL,
begin_time timestamp NOT NULL,
end_time timestamp
)
Run Code Online (Sandbox Code Playgroud)
对于每个feature_id,可能有多行,其时间范围由begin_time/end_time指定.它们可能重叠,但这种情况相对较少.我正在寻找一种快速查找所有具有/没有任何重叠的feature_ids的方法.
我尝试使用窗口函数执行此操作,如下所示:
SELECT feature_id, bool_or(end_time > lead(begin_time) OVER ts_win) OVER ts_win AS overlaps_any
FROM my_features
WINDOW ts_win AS (PARTITION BY feature_id ORDER BY begin_time)
Run Code Online (Sandbox Code Playgroud)
...但这不起作用:
ERROR: window function calls cannot be nested
Run Code Online (Sandbox Code Playgroud)
算法很简单:通过begin_time对给定feature_id的行进行排序,并检查是否有end_time>下一个begin_time(如果有的话).我怀疑必须有一个简单的方法来做到这一点,也许是使用tsrange函数,但现在似乎无法找到它.
a_h*_*ame 22
这确实可以使用范围类型来完成.
以下选择具有重叠范围的所有行:
select f1.*
from my_features f1
where exists (select 1
from my_features f2
where tsrange(f2.begin_time, f2.end_time, '[]') && tsrange(f1.begin_time, f1.end_time, '[]')
and f2.feature_id = f1.feature_id
and f2.id <> f1.id);
Run Code Online (Sandbox Code Playgroud)
当您更改条件时,NOT EXISTS您将找到那些没有任何重叠范围的条件.
SQLFiddle示例:http://sqlfiddle.com/#!15/40b1e/1
tsrange(f2.begin_time, f2.end_time, '[]')创建一个包含上限和下限的范围.您还可以创建排除其中一个或两个的范围.
更多细节可以在手册中找到:http:
//www.postgresql.org/docs/current/static/rangetypes.html#RANGETYPES-INCLUSIVITY
的&&操作者检查是否两个范围重叠:http://www.postgresql.org/docs/current/static/functions-range.html
(我只是希望甲骨文有这样的东西......)