从表中检测范围和计数

时间:2013-06-21 08:33:49

标签: sql postgresql range detect

按组排序的2列的表格,编号:

group_id | number 
---------+--------
   1     |  101
   1     |  102
   1     |  103
   1     |  106
   2     |  104
   2     |  105
   2     |  107

我应该编写什么SQL查询来获得以下输出:

group_id | number_from | number_to  | total 
---------+-------------+------------+-------
   1     |     101     |    103     |   3
   1     |     106     |    106     |   1
   2     |     104     |    105     |   2
   2     |     107     |    107     |   1

3 个答案:

答案 0 :(得分:1)

我用它作为示例表:

create table temp (id int, val int)
insert into temp values (1,101),(1,102),(2,102),(2,104),(2,107)
insert into temp values (2,103)
insert into temp values (2,105)
insert into temp values (2,108)
insert into temp values (2,110)

这就是你想要的:

select t1id,cnt, min(t1val) as min, max(t1val), count(t1val) 
from (
    select tt1.*, 
    (select count (*) from 
        (
            select t1.id as t1id,
            t1.val as t1val,
            (select val from temp t2 where t1.id = t2.id and t2.val = t1.val+1 ) as t2val,
            row_number() over (order by t1.id, t1.val ) as rn
            from temp t1
        ) tt2
        where tt2.t2val is null and tt2.rn < tt1.rn
    ) cnt
    from (
        select t1.id as t1id,
        t1.val as t1val,
        (select val from temp t2 where t1.id = t2.id and t2.val = t1.val+1 ) as t2val,
        row_number() over (order by t1.id, t1.val ) as rn
        from temp t1
    ) tt1
)ttt1
group by t1id, cnt
order by t1id, min

更新:修复了表格未分类的错误)

答案 1 :(得分:1)

Here is SQL Fiddel Demo

以下是脚本

create table Temp(A int,B int);

insert into temp values (1,101);
insert into temp values (1,102);
insert into temp values (1,103);
insert into temp values (1,106);
insert into temp values (2,104);
insert into temp values (2,105);
insert into temp values (2,107);


Select T2.A "group_id",
        Min(T2.B) "number_from",
        Max(T2.B) "number_to",
        Max(T2.E) "total"
from
(
  select *,(B-C) D,
      rank() over 
      (PARTITION by T.A,(B-C) order by T.A,T.B) E,
      rank() over
      (order by T.A,(B-C)) F
  from
  (select A,B,row_number() 
         over (order by (select 0)) C 
   from temp) T
) T2
group by T2.A,T2.D,T2.F
order by 1,2

答案 2 :(得分:1)

WITH RECURSIVE rope AS (
    SELECT i1.id AS low
     , i1.id AS high
     , i1.grp AS grp
     , 1::integer AS cnt
    FROM islands i1
            -- no left neighbor
    WHERE NOT EXISTS ( SELECT * FROM islands x WHERE x.grp = i1.grp AND x.id = i1.id-1)
    UNION ALL
    SELECT ch.low AS low
     , i2.id AS high
     , i2.grp AS grp
     , 1+ch.cnt AS cnt
    FROM islands i2
            -- connect to left neighbor
    JOIN rope ch ON i2.grp = ch.grp AND i2.id = ch.high+1
    )
SELECT * FROM rope r
    -- suppress subchains
WHERE NOT EXISTS (
    SELECT * FROM rope nx
    WHERE nx.low = r.low AND nx.cnt > r.cnt
    )
    ;