Se eri su 11G potresti usare unpivot
:
SELECT subject, AVG(percentage) AS percentage
FROM (
SELECT * FROM tablea
UNPIVOT (percentage FOR subject IN (math, science, computer))
)
GROUP BY subject
ORDER BY subject;
SUBJECT PERCENTAGE
-------- ----------
COMPUTER 94.33
MATH 91.33
SCIENCE 87.33
Ma dato che non lo sei, puoi fingere. Adattamento da questo sito :
SELECT subject, AVG(percentage) AS percentage
FROM (
SELECT DECODE(unpivot_row, 1, 'Math',
2, 'Science',
3, 'Computer') AS subject,
DECODE(unpivot_row, 1, math,
2, science,
3, computer) AS percentage
FROM tablea
CROSS JOIN (SELECT level AS unpivot_row FROM dual CONNECT BY level <= 3)
)
GROUP BY subject
ORDER BY subject;
SUBJECT PERCENTAGE
-------- ----------
Computer 94.33
Math 91.33
Science 87.33
In entrambi i casi, il select
interno sta trasformando le righe in colonne; in 10 g devi solo farlo da solo. Il SELECT ... CONNECT BY ...
genera solo un elenco di valori fittizi e questo deve avere abbastanza per coprire il numero di colonne che stai convertendo in righe (e se ne hai davvero 1000, dovresti davvero rivisitare il modello di dati). I due decode
le istruzioni utilizzano quel numero generato per abbinare il nome e il valore di una colonna:esegui la selezione interna da sola per vedere come appare.
Senza ricorrere all'SQL dinamico, non puoi evitare di dover elencare le colonne - solo una volta con il vero unpivot
, ma due volte con la versione falsa da 10 g, e devi assicurarti che corrispondano correttamente e che il generatore di numeri di riga stia producendo valori sufficienti. (Troppi e potresti ottenere risultati strani, ma poiché tutti i valori extra saranno nulli qui e stai usando avg
, non importa molto in questo caso; proprio come un controllo di integrità dovresti probabilmente farlo corrispondere esattamente comunque).
O un'altra versione, in base al fatto che desideri sempre tutte le colonne tranne name
, il che significa che devi elencare le colonne che desideri solo una volta ed è più facile abbinarle visivamente:continua ad aggiungere when
clausole; e non hai bisogno del conteggio delle righe:
SELECT subject, AVG(percentage) AS percentage
FROM (
SELECT column_name AS subject,
CASE
WHEN column_name = 'MATH' then math
WHEN column_name = 'SCIENCE' then science
WHEN column_name = 'COMPUTER' then computer
END AS percentage
FROM tablea
CROSS JOIN (
SELECT column_name
FROM user_tab_columns
WHERE table_name = 'TABLEA'
AND column_name != 'NAME'
)
)
GROUP BY subject
ORDER BY subject;
SUBJECT PERCENTAGE
------------------------------ ----------
COMPUTER 94.33
MATH 91.33
SCIENCE 87.33