0

具有按组排序的 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
4

3 回答 3

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

更新:如果表未排序,则修复错误)

于 2013-06-21T09:33:04.137 回答
1

这是 SQL Fiddel 演示

下面是脚本

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
于 2013-06-21T10:22:00.443 回答
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
    )
    ;
于 2013-06-21T11:50:01.493 回答