2012-04-02 12 views
11

mam jakiś stolik jak tenGrupa wartościami, które są w kolejności

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

i muszę uzyskać wynik jak ten

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

więc muszę grupy chequeNo gdzie wartości byłaby sekwencyjna bez żadnych przerw. chequeNo jest unikalną kolumną. Dodatkowo powinno się to zrobić za pomocą jednego kwerendy wyboru sql, ponieważ nie mam uprawnień do tworzenia żadnych struktur sql z wyjątkiem wybranych zapytań.

Czy to możliwe?

Byłby wdzięczny za wszelką pomoc

+7

A baza jesteś używanie to? – Thilo

+4

Albo twój przykład nie ma sensu, albo brakuje mi czegoś. –

+1

Czy jesteś pewien, że pożądany wynik, który napisałeś powyżej, jest poprawny? Nie widzę w tym żadnego wzorca. –

Odpowiedz

2

To powinno działać z Oracle 10 (tylko przetestowane z 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 

(powinien działać ze wszystkimi DBMS wspierających standardem SQL funkcje okienkowe, np PostgreSQL, DB2, SQL Server 2012)

21

można wykorzystywać technikę Aketi Jyuuzou zadzwonił Tabibitosan tutaj:

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. 

Pozdrawiam,
Rob.

+0

Bardzo fajnie. O wiele bardziej elegancko niż moje rozwiązanie. –

+2

+1 dzięki podając nazwę techniki, ta odrobina dodatkowej informacji przekształca "tutaj jest twoja odpowiedź 1308044" na "tutaj jest ogólna technika, którą powinieneś wiedzieć." –

+0

wielkie dzięki. Zintegrowałem to rozwiązanie z prawdziwymi zapytaniami i teraz działa dobrze. – Harrison

0

Oto podejście „plain vanilla”:

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 

Proszę dać mi znać, jeśli jest zbyt nieskuteczny dla dużych zbiorów danych.

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

Wynik:

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

Gdybyśmy wzbogacanie rzeczy trochę ...

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

... otrzymujemy:

from     to      
---------------------- ---------------------- 
15      20      
35      35      
Powiązane problemy