2016-08-30 3 views
2

Was ist die beste Variante zum Erstellen von Abfrage zum Sammeln von Zeilen in Spalten wie Pivot, aber ohne Aggregation und mehrere Zeilen können in jeder Spalte sein?SQL-Abfrage: Pivot, aber mit unterschiedlicher Anzahl oder Zeilen

Beispieldaten:

id, parent_fk, month, quantity 
10, 1111, 'jan', 21 
11, 1111, 'jan', 24 
12, 1111, 'feb', 12 

13, 2222, 'jan', 3 
14, 2222, 'feb', 4 
15, 2222, 'mar', 5 

16, 3333, 'feb', 77 
17, 3333, 'feb', 88 
16, 3333, 'mar', 99 

Jeder Monat unterschiedliche Anzahl von Zeilen enthalten. Ich muss sie nebeneinander stellen und durch Höhen rechtfertigen. Ich möchte diese Daten zeigen, wie:

parent_fk, jan, feb, mar 
1111, 21, 12, __ 
1111, 24, __, __ 
2222,  3, 4, 5 
3333, __, 77, 99 
3333, __, 88, __ 

Zur Zeit habe ich eine solche nicht-elegante query (erstellen in jedem Monat mit row_number über Partition Bestellung und von dieser Bestellung alle monthes join):

select 
    nvl(JAN.parent_fk, nvl(FEB.parent_fk, nvl(MAR.parent_fk, -1))) calc_parent_fk, 
    JAN.quantity jan, 
    FEB.quantity feb, 
    MAR.quantity mar 
from 
    (select id, parent_fk, quantity, 
    row_number() OVER (PARTITION BY parent_fk, mnth order by id) "RN" 
    from T_MONTH_DATA 
    where mnth = 'jan') JAN 
full join 
    (select id, parent_fk, quantity, 
    row_number() OVER (PARTITION BY parent_fk, mnth order by id) "RN" 
    from T_MONTH_DATA 
    where mnth = 'feb') FEB 
    on JAN.parent_fk = FEB.parent_fk and JAN.RN = FEB.RN 
full join 
    (select id, parent_fk, quantity, 
    row_number() OVER (PARTITION BY parent_fk, mnth order by id) "RN" 
    from T_MONTH_DATA 
    where mnth = 'mar') MAR 
    on FEB.parent_fk = MAR.parent_fk and FEB.RN = MAR.RN 
order by 1 

Gibt es eine einfachere Möglichkeit, solche Daten zu präsentieren? Wie erhält man parent_fk? (Ich benutze verschachtelte NVL, weil ich nicht weiß, welcher der Monate maximal Zeilen enthält, und alle anderen Monhhes haben dort null).

Antwort

2

In Oracle 11g Verwendung pivot Klausel und Funktion row_number() wie folgt aus:

select parent_fk, jan, feb, mar 
    from ( 
    select row_number() over (partition by mnth, parent_fk order by id) rn, 
      parent_fk, mnth, quantity 
     from t_month_data) 
    pivot (sum(quantity) for mnth in ('jan' jan, 'feb' feb, 'mar' mar)) 
    order by parent_fk 

Testdaten und Ausgang:

create table t_month_data (id number(4), parent_fk number(4), 
          mnth varchar2(3), quantity number(6)); 

insert into t_month_data values (10, 1111, 'jan', 21); 
insert into t_month_data values (11, 1111, 'jan', 24); 
insert into t_month_data values (12, 1111, 'feb', 12); 
insert into t_month_data values (13, 2222, 'jan', 3); 
insert into t_month_data values (14, 2222, 'feb', 4); 
insert into t_month_data values (15, 2222, 'mar', 5); 
insert into t_month_data values (16, 3333, 'feb', 77); 
insert into t_month_data values (17, 3333, 'feb', 88); 
insert into t_month_data values (16, 3333, 'mar', 99); 

PARENT_FK  JAN  FEB  MAR 
--------- ---------- ---------- ---------- 
    1111   21   12 
    1111   24    
    2222   3   4   5 
    3333     77   99 
    3333     88 
+0

Danke, @Ponder Stibbons, sehr schöne Lösung. Zusätzliche Frage: wenn ich die Eingabedaten in verschiedenen Tabellen (eine für jeden Monat), wie Sie sie horizontal verbinden? – zmila

+1

Wahrscheinlich müssen Sie sie alle zuerst zusammenfügen ("union all"). Die Ruhe ist gleich. –

Verwandte Themen