Hvis du var på 11G, kunne du bruge 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
Men da du ikke er det, kan du fake det. Tilpasning fra dette websted :
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
I begge tilfælde er den indre select
omdanner rækker til kolonner; i 10g skal du bare gøre det selv. SELECT ... CONNECT BY ...
genererer bare en liste over dummy-værdier, og denne skal have nok til at dække antallet af kolonner, du konverterer til rækker (og hvis du virkelig har 1000, bør du virkelig gense datamodellen). De to decode
sætninger bruger det genererede tal til at matche et kolonnenavn og en værdi - kør den indre markering alene for at se, hvordan den ser ud.
Uden at ty til dynamisk SQL kan du ikke komme væk fra at skulle liste kolonnerne - kun én gang med den rigtige unpivot
, men to gange med den falske 10g-version, og du skal sikre dig, at de matcher korrekt, og at rækkenummergeneratoren producerer nok værdier. (For mange, og du kan få mærkelige resultater, men da alle ekstra værdier vil være nul her, og du bruger avg
, det betyder ikke så meget i dette tilfælde; bare som en fornuftskontrol bør du nok få det til at matche nøjagtigt alligevel).
Eller en anden version, baseret på at du altid vil have alle kolonnerne undtagen name
, hvilket betyder, at du kun behøver at angive de kolonner, du ønsker én gang, og det er nemmere at matche dem visuelt - bare fortsæt med at tilføje when
klausuler; og du behøver ikke rækkeantallet:
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