SQL:仅选择具有与其他结果相隔给定间隔的值的行

时间:2017-02-10 23:44:17

标签: sql postgresql recursive-query

让我们说我有一张看起来像这样的桌子,在几秒钟内给我一些各种活动的时间。

event_time
----------
11
14
18
20
25
39
42
43
50

我正在尝试提供一个查询,该查询将从此表中为我提供一组行,其中每行与结果中的其他行相隔至少10秒。

期望的结果是:

event_time
----------
11
25
39
50

包含event_time=11的行,因为它前面没有任何内容。 event_time=25的行是下一个要返回的行,因为它是距离event_time=11行的第一行至少10秒。

我正在使用Postgres。我可以使用递归查询/ CTE执行此操作,但如果不使用ORDER BY,LIMIT等子句就无法完成此操作,Postgres显然不允许在递归查询中使用这些。

3 个答案:

答案 0 :(得分:2)

您可以使用plpgsql,这对于大型数据集来说似乎很简单且非常有效(与假设的递归查询相比)。

create or replace function strain_events()
returns setof events language plpgsql as $$
declare
    curr record;
    prev int;
begin
    for curr in
        select *
        from events
        order by 1
    loop
        if prev is null or curr.event_time >= prev + 10 then
            return next curr;
            prev = curr.event_time;
        end if;
    end loop;
end $$;

select * from strain_events();

答案 1 :(得分:2)

  

我可以使用递归查询/ CTE执行此操作,但如果不使用ORDER BY,LIMIT等子句就无法完成此操作,Postgres显然不允许在递归查询中使用这些。

with recursive 
  t(x) as ( --Test data
    select * from unnest('{11,14,18,20,25,39,42,43,50,55,60,61,69,70,71}'::int[])
    order by random()),
  r(x) as (
    select min(x) as x from t
    union all
    (select t.x from t join r on (t.x >= r.x + 10) order by t.x limit 1))
select * from r;

http://rextester.com/VHOGH66762

但我个人更喜欢the solution with stored function

答案 2 :(得分:0)

我认为此查询可以正常工作

select distinct  event_time_b
from
(
select event_time_a , min(event_time_b) event_time_b
from
(
select a.event_time event_time_a , b.event_time event_time_b , b.event_time-a.event_time diff
 from (select 0 as event_time union select event_time from  so_ques) a , so_ques b
where a.event_time<>b.event_time
and  b.event_time-a.event_time>=10
order by a.event_time
) a
group by event_time_a
order by event_time_a
) a
order by 1
;

表名= so_ques (为测试而创建)