2016-12-20 58 views
7

Potrzebuję zapytać o tabelę, zawierającą identyfikator kroku + wartość. Wynik wyświetli interwały z przypisaną wartością. Odstępy są definiowane jako "ciąg następujących po sobie kolejnych kroków, dzielących tę samą wartość danych".Oracle - wartości grupujące się wzdłuż przedziału

Mam twardy czas opisujące go w słowach, więc proszę zobaczyć:

Od tej tabeli

Step ! Data 
    ------------ 
    1 ! A 
    2 ! A 
    3 ! A 
    5 ! A 
    6 ! B 
    10 ! A 

muszę Poniższy raport

From ! To ! Data 
    ------------------- 
    1 ! 3 ! A 
    5 ! 5 ! A 
    6 ! null ! B 
    10 ! null ! A 

Myślałem prowadzenie() pomogłoby mi tutaj, ale się nie udało.

+2

Wydaje się, że dane są rozpatrywane oddzielnie dla wartości A i B? Następnie: Dlaczego wynik (5, 5) dla tego wiersza, ale następnie (6, NULL), a nie (6, 6)? – mathguy

+0

Och ... więc, dla OSTATNICH wystąpień każdej wartości "Dane", interwał powinien być otwarty, ale wszystkie inne interwały są "zamknięte"? – mathguy

+0

Masz rację, nadal jest to trochę przesadzone: wartości "To", które są identyczne jak "Od" zamiast NULL, są całkowicie dopuszczalne. – user2999190

Odpowiedz

1
select  min (step)             as "from" 
      ,nullif (max (step),max(min(step)) over (partition by data)) as "to" 
      ,data 

from  (select  step,data 
         ,row_number() over (partition by data order by step) as n 

      from  t 
      ) 

group by data 
      ,step - n    

order by "from"   
+0

Przykładowy wynik, nie powinien mieć "5! zero ! A' zamiast '5! 5! A'? –

+0

NULL wskazuje tylko ostatni interwał otwarty. Jak widać, dla wartości A, nowy interwał rozpoczyna się w kroku 10, dlatego też zaczyna się tam także okres rozpoczynający się od 5. – user2999190

+0

Dzięki. Zobacz zaktualizowaną odpowiedź –

1

Możesz to zrobić, generując sekwencję liczb i odejmując od step. To będzie stała, gdy wartości są sekwencyjne:

select min(step) as from_step, max(step) as to_step, data 
from (select t.*, 
      row_number() over (partition by data order by step) as seqnum 
    from t 
    ) t 
group by (step - seqnum), data; 

EDIT:

Nie jest całkiem jasne, gdzie NULL s pochodzą. Jeśli będę spekulować, że są to ostatnie wartości dla każdej wartości, można zrobić:

select min(step) as from_step, 
     (case when max(step) <> max_step then max(step) end) as to_step, 
     data 
from (select t.*, 
      max(step) over (partition by data) as max_step 
      row_number() over (partition by data order by step) as seqnum 
    from t 
    ) t 
group by (step - seqnum), data, max_step; 
+0

PO nie wyjaśnił tego bardzo dobrze, ale wydaje się, że dane są podzielone na wartości (patrz punkty 5-6). – mathguy

+0

@mathguy. . . Tak właśnie działa to rozwiązanie. –

+2

@GordonLinoff nie "numer_wiersza" to 'partycja według danych' lub przynajmniej użyj' danych' w klauzulach 'order'? – Kacper