实际查询涉及更多,但我面临的问题可以归结为:
用于过滤单调递增整数的行集的查询,以便 - 最终结果集中的,行(n + 1).value> = row(n).value + 5 的
对于我需要解决的实际问题,行集计数在1000s内。
澄清一些例子:
我已经设法通过以下查询获得所需的结果,但它似乎过于复杂。取消注释不同的“..with t(k)..”以试用它们。
我正在寻找任何简化或替代方法来获得相同的结果。
with recursive r(n, pri) as (
with t(k) as (values (1),(2),(3),(4),(5)) -- the data we want to filter
-- with t(k) as (values (1),(5),(7),(10),(11),(12),(13))
-- with t(k) as (values (6),(8),(11),(16),(20),(23))
-- with t(k) as (values (6),(8),(12),(16),(20),(23))
select min(k), 1::bigint from t -- bootstrap for recursive processing. 1 here represents rank().
UNION
select k, (rank() over(order by k)) rr -- rank() is required just to filter out the rows we dont want from the final result set, and no other reason
from r, t
where t.k >= r.n+5 and r.pri = 1 -- capture the rows we want, AND unfortunately a bunch of rows we dont want
)
select n from r where pri = 1; -- filter out the rows we dont want
答案 0 :(得分:0)
使用plpgsql怎么样?
drop table if exists t;
create table t(k) as (
values
(1),(2),(3),(4),(5)
--(1),(5),(7),(10),(11),(12),(13)
--(6),(8),(11),(16),(20),(23)
--(6),(8),(12),(16),(20),(23)
);
create or replace function foo(in n int, out k int) returns setof int as $$
declare
r t;
rp t;
begin
rp := null;
for r in (select * from t) loop
if (rp is null) or (r.k >= rp.k + n) then
rp := r;
k := r.k;
return next;
end if;
end loop;
return;
end; $$ immutable language plpgsql;
select * from foo(5);
答案 1 :(得分:0)
-- The data:
CREATE TABLE rowseq(val INTEGER NOT NULL) ;
INSERT INTO rowseq(val ) values
-- (1),(2),(3),(4),(5)
(1), (5), (7), (10), (11), (12), (13)
--(6),(8),(11),(16),(20),(23)
--(6),(8),(12),(16),(20),(23)
;
-- need this view, because a recursive CTE cannot be based on a CTE
-- [we could also duplicate the row_number() in both legs of the recursive CTE]
CREATE TEMP VIEW qqq AS
SELECT val, row_number() OVER (ORDER BY val) AS rn
FROM rowseq
;
WITH RECURSIVE rrr AS (
SELECT qqq.val, qqq.rn
FROM qqq
WHERE qqq.rn = 1
UNION
SELECT q1.val, q1.rn
FROM rrr
JOIN qqq q1 ON q1.rn > rrr.rn AND q1.val >= rrr.val+5 -- The "Gap" condition
AND NOT EXISTS ( SELECT * FROM qqq nx -- But it must be the FISRT match
WHERE nx.rn > rrr.rn AND nx.val >= rrr.val+5 -- same condition
AND nx.rn < q1.rn -- but NO earlier match
)
)
-- prove it to the world!
SELECT *
FROM rrr
;