Transponieren von Zeilen

shellycooper

Benutzer
Beiträge
6
Hallo :)

ich stehe gerade vor einem für mich aktuell unlösbarem Problem :

Ich habe eine Tabelle in der jede Aktualisierung für ein Materialstück mit einer neuen Zeile realisiert wird. D.h. Materialstück x hat z.B. für jedes durchlaufene Lager einen neuen Datensatz in dem der Durchsatzzeitpunkt und das Lager geschrieben werden. Um eine sinnvolle Beziehung herzustellen brauche ich aber die Daten in einer Zeile hintereinander geschrieben (nach Zeit sortiert) anstatt z.B. 10 Zeilen untereinander. Also will ich die Daten transponieren.

Für ein einzelnes Materialstück habe ich das gelöst indem ich die Zeitstempel ordne und anhand der Zeilennummer die Ergebnisse in dafür generierte Felder schreibe:

select
materialident
,Lager1
,Zeitpunkt_Lager1
,Lager2
,Zeitpunkt_Lager2
,Lager3
,Zeitpunkt_Lager3
,Lager4
,Zeitpunkt_Lager4
,Lager5
,Zeitpunkt_Lager5
,Lager6
,Zeitpunkt_Lager6
,Lager7
,Zeitpunkt_Lager7
,Lager8
,Zeitpunkt_Lager8
,Lager9
,Zeitpunkt_Lager9
,Lager10
,Zeitpunkt_Lager10
from
(
select materialident
,max(decode(rownum,1,Lager,null)) Lager1
,max(decode(rownum,1,zeitpunkt,null)) Zeitpunkt_Lager1
,max(decode(rownum,2,Lager,null)) Lager2
,max(decode(rownum,2,zeitpunkt,null)) Zeitpunkt_Lager2
,max(decode(rownum,3,Lager,null)) Lager3
,max(decode(rownum,3,zeitpunkt,null)) Zeitpunkt_Lager3
,max(decode(rownum,4,Lager,null)) Lager4
,max(decode(rownum,4,zeitpunkt,null)) Zeitpunkt_Lager4
,max(decode(rownum,5,Lager,null)) Lager5
,max(decode(rownum,5,zeitpunkt,null)) Zeitpunkt_Lager5
,max(decode(rownum,6,Lager,null)) Lager6
,max(decode(rownum,6,zeitpunkt,null)) Zeitpunkt_Lager6
,max(decode(rownum,7,Lager,null)) Lager7
,max(decode(rownum,7,zeitpunkt,null)) Zeitpunkt_Lager7
,max(decode(rownum,8,Lager,null)) Lager8
,max(decode(rownum,8,zeitpunkt,null)) Zeitpunkt_Lager8
,max(decode(rownum,9,Lager,null)) Lager9
,max(decode(rownum,9,zeitpunkt,null)) Zeitpunkt_Lager9
,max(decode(rownum,10,Lager,null)) Lager10
,max(decode(rownum,10,zeitpunkt,null)) Zeitpunkt_Lager10
from
(
select rownum, materialident,Lager,zeitpunkt
from
Tabelle
where materialident=xxx
order by zeitpunkt asc

)
group by materialident
);

Das funktioniert einwandfrei allerdings nur für ein Materialstück das ich explizit auswähle. Will ich das für alle Materialstücke in der Tabelle machen, klappt das natülich nicht da die Zeilennummer nicht automatisch bei einem neuen Materialidenten bei 1 anfängt sondern weiterläuft.

Im Grunde muss ich diese Anweisung als Schleife für jedes Materialstück ausführen und bei Identwechsel wieder bei Zeile 1 anfangen.

So wie ich das gesehen habe, würde das mit einem Cursor gehen? Aber PL/SQL hab ich bisher garnicht gekannt. Vielleicht kann mir jemand die Abfrage dahingehend etwas umschreiben? Das wäre echt eine Riesenhilfe!

Oder gibt es sonst eine andere gangbare Lösung für das Transponieren von Daten?

Besten Dank vorab
 
Werbung:
Du solltest dich mal mit dem "PIVOT"-Befehl beschäftigen...
Code:
SQL> Select *
  2  From   fps_max_test;
MATERIALIDENT LAGER                                    ZEITPUNKT
------------- ---------------------------------------- -----------
            1 A                                        10.07.2015
            1 B                                        10.07.2015
            1 C                                        10.07.2015
            2 A                                        10.07.2015
            2 B                                        10.07.2015
            2 C                                        10.07.2015
6 rows selected

SQL>
SQL> Select materialident,
  2         lager_a_l,
  3         lager_a_z,
  4         lager_b_l,
  5         lager_b_z
  6  From   fps_max_test
  7  Pivot
  8  (
  9    Max(lager) as l, Max(zeitpunkt) as z for lager In ('A' as lager_a, 'B' as lager_b)
10  );
MATERIALIDENT LAGER_A_L                                LAGER_A_Z   LAGER_B_L                                LAGER_B_Z
------------- ---------------------------------------- ----------- ---------------------------------------- -----------
            1 A                                        10.07.2015  B                                        10.07.2015
            2 A                                        10.07.2015  B                                        10.07.2015

SQL>
 
Hey, Danke für die schnelle Antwort! Ich habe versucht die Abfrage so auszuführen. Das Ergebnis war aber leider, das ich für ein Materialstück 11 Datensätze bekomme (11 Bewegungen sind geloggt), allerdings 1x gefüllt mir Lager "A" und 1x mit Lager "B". Die restlichen Felder sind leer. Das klappt so leider nicht. Auch kann ich nicht sagen in welcher Reihenfolge welche Lager vorkommen und es kann sein, dass Lager mehrfach vorkommen durch Hin- und Rücktransport.

Select materialident,
lager_a_l,
lager_a_z,
lager_b_l,
lager_b_z
From Tabelle_Lager
Pivot
( Max(lager) as l, Max(zeitpunkt) as z for lager In ('A' as lager_a, 'B' as lager_b)
)
where mat_ident=xxx
;

Ergebis:

MATERIALIDENT LAGER_A_L LAGER_A_Z LAGER_B_L LAGER_B_Z
xxx
xxx
xxx
xxx
xxx
xxx
xxx
xxx A 01.07.15
xxx
xxx
xxx

Entweder ich mache was falsch oder Pivot ist leider nicht meine Lösung. Die Abfrage wie ich sie gemacht hatte lieferte schon genau das Ergebnis das ich haben will aber nur für 1 bestimmtes Stück und nicht als Massenabfrage
 
Werbung:
Mein Fehler...
Pivot gruppiert nach allen Spalten die du nicht referenzierst... D.h. da du lager und zeitpunkt aggregierst (und als Auswahlkriterium verwendest) fallen die beiden schonmal weg... du musst also noch irgend eine spalte haben die keine eindeutigen Werte pro Stück führt.

Das sollte das Problem lösen
Code:
Select materialident
      ,a_l
      ,a_z
      ,b_l
      ,b_z
      ,c_l
      ,c_z
From  (Select distinct materialident
             ,lager
             ,zeitpunkt
       From   shellycooper
       Where lager In ('A', 'B', 'C')
)
Pivot
(
  Max(lager) as l, Max(zeitpunkt) as z For lager In ('A' as a, 'B' as b, 'C' as c)
);
 
Zuletzt bearbeitet:
Zurück
Oben