SQL:Select 行仅包含与其他结果按给定间隔分隔的值
SQL: Select rows only with values separated by a given interval from other results
假设我有一个看起来像这样的 table,以秒为单位为我提供各种事件的时间。
event_time
----------
11
14
18
20
25
39
42
43
50
我正在尝试提出一个查询,该查询将为我提供此 table 中的一组行,其中每行与 中的其他行至少间隔 10 秒结果.
期望的结果是:
event_time
----------
11
25
39
50
包含 event_time=11
的行,因为它前面没有任何内容。 event_time=25
的行是下一个要返回的行,因为它是距离 event_time=11
.
的行至少 10 秒的第一行
我正在使用 Postgres。我可以用递归查询/CTE 来做到这一点,但如果不使用 ORDER BY、LIMIT 等子句就无法完成这项工作,而 Postgres 显然不允许在递归查询中使用这些。
你可以使用 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();
我认为这个查询可行
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
;
Table name = so_ques(为测试而创建)
I would be able to do this with a recursive query / CTE, but cannot make that work without using an ORDER BY, LIMIT, etc. clause, and Postgres apparently does not allow these in recursive queries.
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
不过我个人更喜欢.
假设我有一个看起来像这样的 table,以秒为单位为我提供各种事件的时间。
event_time
----------
11
14
18
20
25
39
42
43
50
我正在尝试提出一个查询,该查询将为我提供此 table 中的一组行,其中每行与 中的其他行至少间隔 10 秒结果.
期望的结果是:
event_time
----------
11
25
39
50
包含 event_time=11
的行,因为它前面没有任何内容。 event_time=25
的行是下一个要返回的行,因为它是距离 event_time=11
.
我正在使用 Postgres。我可以用递归查询/CTE 来做到这一点,但如果不使用 ORDER BY、LIMIT 等子句就无法完成这项工作,而 Postgres 显然不允许在递归查询中使用这些。
你可以使用 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();
我认为这个查询可行
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
;
Table name = so_ques(为测试而创建)
I would be able to do this with a recursive query / CTE, but cannot make that work without using an ORDER BY, LIMIT, etc. clause, and Postgres apparently does not allow these in recursive queries.
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
不过我个人更喜欢