2012-04-02 6 views
11

している値で、私はこのグループはシーケンス

row chequeNo 
1  15 
2  19 
3  20 
4  35 
5  16 

のようないくつかのテーブルを持っていると私は、この

row from to  
1 15 16  
2 19 20  
3 35 35 

のような結果を取得する必要がありますので、私は、値がシーケンシャルになりchequeNoのグループが必要いかなる中断もなしに。 chequeNoは一意の列です。さらに、selectクエリ以外のSQL構造を作成する権限がないため、1つのSQL selectクエリで行う必要があります。

これは可能ですか?

は、任意のヘルプ

+7

そして、あなたがしているデータベースをを使って? – Thilo

+4

あなたの例が意味をなさないか、何かが紛失しています –

+1

上記の書き込み結果が正しいと確信していますか?私はそれにパターンがないと思う。 –

答えて

2

これは、Oracleの10で動作するはずです(Oracleのみ11でテスト)のために感謝される

select group_nr + 1, 
     min(chequeno) as start_value, 
     max(chequeno) as end_value 
from (
    select chequeno, 
     sum(group_change_flag) over (order by rn) as group_nr 
    from (
    select row_number() over (order by chequeno) as rn, 
      chequeno, 
      case 
      when chequeno - lag(chequeno,1,chequeno) over (order by chequeno) <= 1 then 0 
      else 1 
      end as group_change_flag 
    from foo 
) t1 
) t2 
group by group_nr 
order by group_nr 

(それは標準SQLのウィンドウ機能をサポートしている任意のDBMS、例えばPostgreSQLので動作するはずです、 DB2、SQL Server 2012の)

21

あなたがAketi Jyuuzouの技術を使用することができますが、ここでTabibitosanと呼ばれる:

SQL> create table mytable (id,chequeno) 
    2 as 
    3 select 1, 15 from dual union all 
    4 select 2, 19 from dual union all 
    5 select 3, 20 from dual union all 
    6 select 4, 35 from dual union all 
    7 select 5, 16 from dual 
    8/

Table created. 

SQL> with tabibitosan as 
    2 (select chequeno 
    3   , chequeno - row_number() over (order by chequeno) grp 
    4  from mytable 
    5 ) 
    6 select row_number() over (order by grp) "row" 
    7  , min(chequeno) "from" 
    8  , max(chequeno) "to" 
    9 from tabibitosan 
10 group by grp 
11/

     row  from   to 
---------- ---------- ---------- 
     1   15   16 
     2   19   20 
     3   35   35 

3 rows selected. 

よろしくございます。
Rob。ここで

+0

非常にクールです。私のソリューションよりもはるかにエレガントです。 –

+2

+1テクニックの名前を与えてくれてありがとうございます。ちょっとした情報があれば、ここにあなたの答えは1308044です。 –

+0

ありがとうございました。私はこのソリューションを実際のクエリに統合しましたが、現在はうまく機能しています。 – Harrison

0

は「プレーン・バニラ」のアプローチです:

SELECT T1.chequeNo, T2.chequeNo 
FROM Table1 AS T1 INNER JOIN Table1 AS T2 ON T2.chequeNo >= T1.chequeNo 
WHERE 
NOT EXISTS (SELECT T0.chequeNo FROM Table1 T0 WHERE T0.chequeNo IN ((T1.chequeNo-1), (T2.chequeNo+1))) 
AND (SELECT COUNT(*) FROM Table1 T0 WHERE T0.chequeNo BETWEEN T1.chequeNo AND T2.chequeNo)=(T2.chequeNo - T1.chequeNo + 1) 
ORDER BY 1,2 

それは大規模なデータセットのためにあまりにも非効率的だ場合は私に知らせてください。

0
CREATE TABLE YOUR_TABLE (
    chequeNo NUMBER PRIMARY KEY 
); 

INSERT INTO YOUR_TABLE VALUES (15); 
INSERT INTO YOUR_TABLE VALUES (19); 
INSERT INTO YOUR_TABLE VALUES (20); 
INSERT INTO YOUR_TABLE VALUES (35); 
INSERT INTO YOUR_TABLE VALUES (16); 

SELECT T1.chequeNo "from", T2.chequeNo "to" 
FROM 
    (
     SELECT chequeNo, ROW_NUMBER() OVER (ORDER BY chequeNo) RN 
     FROM (
      SELECT chequeNo, LAG(chequeNo) OVER (ORDER BY chequeNo) PREV 
      FROM YOUR_TABLE 
     ) 
     WHERE PREV IS NULL OR chequeNo > PREV + 1 
    ) T1 
    JOIN 
    (
     SELECT chequeNo, ROW_NUMBER() OVER (ORDER BY chequeNo) RN 
     FROM (
      SELECT chequeNo, LEAD(chequeNo) OVER (ORDER BY chequeNo) NEXT 
      FROM YOUR_TABLE 
     ) 
     WHERE NEXT IS NULL OR chequeNo < NEXT - 1 
    ) T2 
    USING (RN); 

結果:我々は少し物事を盛り上げる場合

from     to      
---------------------- ---------------------- 
15      16      
19      20      
35      35      

が...

INSERT INTO YOUR_TABLE VALUES (17); 
INSERT INTO YOUR_TABLE VALUES (18); 

が...我々が得る:

from     to      
---------------------- ---------------------- 
15      20      
35      35      
関連する問題