11G を使用している場合は、次を使用できます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
しかし、あなたはそうではないので、それを偽造することができます. このサイトからの適応:
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
どちらの場合も、内側select
は行を列に変換しています。10g では、自分で行う必要があります。ダミー値のSELECT ... CONNECT BY ...
リストを生成するだけで、これは行に変換する列の数をカバーするのに十分でなければなりません (実際に 1000 ある場合は、データ モデルを実際に再検討する必要があります)。2 つのdecode
ステートメントは、その生成された数値を使用して、列名と値を一致させます。内部選択を単独で実行して、それがどのように見えるかを確認します。
動的 SQL に頼らなければ、列をリストする必要から逃れることはできません。本物の 10g バージョンでは 1 回だけunpivot
ですが、偽の 10g バージョンでは 2 回です。十分な価値を生み出しています。(多すぎると奇妙な結果が得られる可能性がありますが、ここでは余分な値が null になり、 を使用してavg
いるため、この場合はあまり問題になりません。サニティ チェックと同様に、とにかく正確に一致させる必要があります) .
または、常に を除くすべての列name
が必要であることに基づいた別のバージョンです。つまり、必要な列を一度だけリストする必要があり、それらを視覚的に一致させる方が簡単when
です。句を追加し続けるだけです。行数は必要ありません。
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