2010-09-02 59 views
4

是否有將允許設置行這樣甲骨文 - 從行轉換價值爲範圍

WITH 
base AS 
(
    SELECT 1 N FROM DUAL UNION ALL 
    SELECT 2 N FROM DUAL UNION ALL 
    SELECT 3 N FROM DUAL UNION ALL 

    SELECT 6 N FROM DUAL UNION ALL 
    SELECT 7 N FROM DUAL UNION ALL 

    SELECT 17 N FROM DUAL UNION ALL 
    SELECT 18 N FROM DUAL UNION ALL 
    SELECT 19 N FROM DUAL UNION ALL 

    SELECT 21 N FROM DUAL 
) 
SELECT a.N 
FROM base a 

取得成果

1  3 
6  7 
17 19 
21 21 

它實際上是一個行範圍內操作的任何技術。 我在甲骨文土地玩,並希望有任何建議。

+0

你如何定義你的範圍是多少?如果他們是3x-1 <= N <= 3x + 1,那麼不應該1和3出現在單獨的行上,即。在不同的範圍內(如1,1和2,3)? – 2010-09-02 17:25:50

+0

@mark 1-3是一組沒有適用的特定公式。 – EvilTeach 2010-09-02 17:55:50

回答

9

我覺得這或許可以得到改善,但它的工作原理:

WITH base AS (
    SELECT 1 N FROM DUAL UNION ALL 
    SELECT 2 N FROM DUAL UNION ALL 
    SELECT 3 N FROM DUAL UNION ALL 
    SELECT 6 N FROM DUAL UNION ALL 
    SELECT 7 N FROM DUAL UNION ALL 
    SELECT 17 N FROM DUAL UNION ALL 
    SELECT 18 N FROM DUAL UNION ALL 
    SELECT 19 N FROM DUAL UNION ALL 
    SELECT 21 N FROM DUAL 
) 
, lagged AS 
(
    SELECT n, LAG(n) OVER (ORDER BY n) lag_n FROM base 
) 
, groups AS 
(
    SELECT n, row_number() OVER (ORDER BY n) groupnum 
     FROM lagged 
     WHERE lag_n IS NULL OR lag_n < n-1 
) 
, grouped AS 
(
    SELECT n, (SELECT MAX(groupnum) FROM groups 
       WHERE groups.n <= base.n 
      ) groupnum 
     FROM base 
) 
SELECT groupnum, MIN(n), MAX(n) 
    FROM grouped 
    GROUP BY groupnum 
    ORDER BY groupnum 
+0

是的,這個工作。 今天我學到了一些新東西。 謝謝戴夫。 – EvilTeach 2010-09-02 17:54:40

+0

+1對分組標準的心靈感應。 – 2010-09-03 11:15:12

0

另一種方式:

WITH base AS 
(
    SELECT 1 N FROM DUAL UNION ALL 
    SELECT 2 N FROM DUAL UNION ALL 
    SELECT 3 N FROM DUAL UNION ALL 
    SELECT 6 N FROM DUAL UNION ALL 
    SELECT 7 N FROM DUAL UNION ALL 
    SELECT 17 N FROM DUAL UNION ALL 
    SELECT 18 N FROM DUAL UNION ALL 
    SELECT 19 N FROM DUAL UNION ALL 
    SELECT 21 N FROM DUAL 
) 
select min(n), max(n) from 
    (
    select n, connect_by_root n root from base 
    connect by prior n = n-1 
    start with n not in (select n from base b 
         where exists (select 1 from base b1 where b1.n = b.n-1) 
         ) 
) 
    group by root 
    order by root 
0

還有一種方法:

with base as (
    select 1 n from dual union all 
    select 2 n from dual union all 
    select 3 n from dual union all 
    select 6 n from dual union all 
    select 7 n from dual union all 
    select 17 n from dual union all 
    select 18 n from dual union all 
    select 19 n from dual union all 
    select 21 n from dual) 
select a,b 
from (select a 
      ,case when b is not null and a is not null 
        then b 
        else lead(n) over (order by n) 
      end b 
     from (select n 
        ,a 
        ,b 
      from (select n 
         ,case n-1 when lag (n) over (order by n) then null else n end a 
         ,case n+1 when lead (n) over (order by n) then null else n end b 
        from base) 
     where a is not null 
     or b is not null)) 
where a is not null 
order by a