2013-06-21 66 views
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 
+1

PostgreSQL的版本? (這與功能可用性有關,因此您應該始終指定它,例如,窗口函數和遞歸CTE僅在8.4中可用)。我也迴應克萊夫:你已經試過了什麼?你卡在哪裏? (順便說一句,「group」是一個關鍵字,因此也是一個可怕的名字)。 –

+0

我試過在函數中使用循環,但似乎不太好。 一個朋友建議我使用遞歸,但我仍然不知道如何使用遞歸爲這種情況下 – nametal

回答

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 
+0

您的查詢效果很好。 非常感謝:) – nametal

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
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 
    ) 
    ;