2017-01-25 4 views
2

Was ich derzeit haben:Oracle SQL Spalten in Zeilen ohne UNPIVOT

Team User Apples Oranges Pears 
Red  Adam 4   5   6 
Red  Avril 11  12   13 
Blue David 21  22   23 

Was gebraucht wird:

Team User Product Count 
Red  Adam Apples  4 
Red  Adam Oranges 5 
Red  Adam Pears  6 
Red  Avril Apples  11 
Red  Avril Oranges 12 
Red  Avril Pears  13 
Blue David Apples  21 
.... 

Dies ist implementiert werden unter Verwendung von Oracle SQL. Ich verstehe, dass dies mit UNPIVOT gemacht werden kann, aber meine Oracle SQL-Version ist zu alt, um diese Methode zu unterstützen. Kann jemand ein Beispiel dafür geben, wie dies mit CROSS APPLY oder ähnlichen Methoden erreicht werden kann? Die Anzahl ändert sich je nach Team-Benutzer-Produkt-Kombination, und die Anzahl der Produkttypen kann sich in der Zukunft leicht ändern, sodass eine skalierbare Lösung erforderlich sein kann.

Dies ist zeitkritisch, deshalb schätze ich die Hilfe.

+2

Sie könnten dies mit einer Reihe von Gewerkschaften tun, aber das wäre ziemlich hässlich. Hast du schon etwas probiert? –

+1

'Auswahl Team, "USER", Äpfel als Produkt von der_Tabelle Union alle wählen Team, "USER", Orangen aus der_Tabelle ... ' –

Antwort

2

Sie können dies mit einem Kreuz-Join und einigen Case-Anweisungen tun, indem Sie eine Dummy-Unterabfrage verwenden, die die gleiche Anzahl von Zeilen enthält wie Spalten, die Sie entfernen möchten (da jede Spalte in eine eigene Zeile gehen soll) so wie:

WITH your_table AS (SELECT 'Red' Team, 'Adam' usr, 4 Apples, 5 Oranges, 6 Pears FROM dual UNION ALL 
        SELECT 'Red' Team, 'Avril' usr, 11 Apples, 12 Oranges, 13 Pears FROM dual UNION ALL 
        SELECT 'Blue' Team, 'David' usr, 21 Apples, 22 Oranges, 23 Pears FROM dual) 
-- end of mimicking your table. See SQL below: 
SELECT yt.team, 
     yt.usr, 
     CASE WHEN d.id = 1 THEN 'Apples' 
      WHEN d.id = 2 THEN 'Oranges' 
      WHEN d.id = 3 THEN 'Pears' 
     END product, 
     CASE WHEN d.id = 1 THEN yt.apples 
      WHEN d.id = 2 THEN yt.oranges 
      WHEN d.id = 3 THEN yt.pears 
     END count_of_product 
FROM your_table yt 
     CROSS JOIN (SELECT LEVEL ID 
        FROM dual 
        CONNECT BY LEVEL <= 3) d -- number of columns to unpivot 
ORDER BY team, usr, product; 

TEAM USR PRODUCT COUNT_OF_PRODUCT 
---- ----- ------- ---------------- 
Blue David Apples    21 
Blue David Oranges    22 
Blue David Pears     23 
Red Adam Apples     4 
Red Adam Oranges    5 
Red Adam Pears     6 
Red Avril Apples    11 
Red Avril Oranges    12 
Red Avril Pears     13 

es auf diese Weise tun bedeutet, dass Sie nur einmal durch den Tisch gehen, anstatt mehrere Male, wenn Sie die Union alle Methode taten.


ETA: Hier ist die Methode, die Aleksej bezog - Ich würde vorschlagen, beide Methoden gegen den Satz von Daten zu testen (was hoffentlich groß genug ist, repräsentativ zu sein) zu sehen, die man performanter ist:

WITH your_table AS (SELECT 'Red' Team, 'Adam' usr, 4 Apples, 5 Oranges, 6 Pears FROM dual UNION ALL 
        SELECT 'Red' Team, 'Avril' usr, 11 Apples, 12 Oranges, 13 Pears FROM dual UNION ALL 
        SELECT 'Blue' Team, 'David' usr, 21 Apples, 22 Oranges, 23 Pears FROM dual) 
-- end of mimicking your table. See SQL below: 
SELECT yt.team, 
     yt.usr, 
     CASE WHEN LEVEL = 1 THEN 'Apples' 
      WHEN LEVEL = 2 THEN 'Oranges' 
      WHEN LEVEL = 3 THEN 'Pears' 
     END product, 
     CASE WHEN LEVEL = 1 THEN yt.apples 
      WHEN LEVEL = 2 THEN yt.oranges 
      WHEN LEVEL = 3 THEN yt.pears 
     END count_of_product 
FROM your_table yt 
CONNECT BY PRIOR team = team 
      AND PRIOR usr = usr 
      AND PRIOR sys_guid() IS NOT NULL 
      AND LEVEL <= 3 
ORDER BY team, usr, product; 

TEAM USR PRODUCT COUNT_OF_PRODUCT 
---- ----- ------- ---------------- 
Blue David Apples    21 
Blue David Oranges    22 
Blue David Pears     23 
Red Adam Apples     4 
Red Adam Oranges    5 
Red Adam Pears     6 
Red Avril Apples    11 
Red Avril Oranges    12 
Red Avril Pears     13 
+0

Ich mag diesen Ansatz; Ich glaube, Sie könnten es sogar vereinfachen, indem Sie das 'JOIN' entfernen und das' CONNECT BY' direkt in der Quelltabelle anwenden, ohne 'DUAL' zu benötigen. – Aleksej

+0

@Aleksej Ich hatte das nicht berücksichtigt; es ist möglich, aber ich weiß nicht, ob es so leistungsfähig wäre. Ich habe leider keine Zeit, um es zu testen. – Boneist

+0

Dieser Ansatz hat mein Problem gelöst und eine erhebliche Menge an Arbeitsstunden gekürzt. Aber ich würde gerne mehr über Aleksejs Idee erfahren. Kannst du mehr Details liefern? – Toon

1

Sie können eine große Vereinigung alle wie folgt verwenden:

select 
    Team, 
    "User", 
    'Apples' Product, 
    Apples "Count" 
from your_table 
union all 
select 
    Team, 
    "User", 
    'Oranges' Product, 
    Oranges "Count" 
from your_table 
union all 
select 
    Team, 
    "User", 
    'Pears' Product, 
    Pears "Count" 
from your_table 
union all 
. . . 

Versuchen Sie auch, nicht Keywords zu verwenden, wie Benutzer oder Count als Bezeichner oder sonst, wickeln Sie sie in doppelte Anführungszeichen wie ich .