Se você estivesse em 11G, poderia usar
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
Mas como você não é, você pode fingir. Adaptação de deste site :
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
Em ambos os casos, o
select
interno está transformando linhas em colunas; em 10g você só tem que fazer você mesmo. O SELECT ... CONNECT BY ...
apenas gera uma lista de valores fictícios, e isso deve ter o suficiente para cobrir o número de colunas que você está convertendo em linhas (e se você realmente tiver 1000, deve realmente revisitar o modelo de dados). Os dois decode
As instruções usam esse número gerado para corresponder a um nome e valor de coluna - execute a seleção interna por conta própria para ver como é. Sem recorrer ao SQL dinâmico, você não pode deixar de listar as colunas - apenas uma vez com o
unpivot
real , mas duas vezes com a versão 10g falsa, e você precisa ter certeza de que eles correspondem corretamente e que o gerador de números de linha está produzindo valores suficientes. (Muitos e você pode obter resultados estranhos, mas como qualquer valor extra será nulo aqui e você está usando avg
, não importa muito neste caso; apenas como uma verificação de sanidade, você provavelmente deve fazer com que corresponda exatamente de qualquer maneira). Ou outra versão, com base em você sempre querendo todas as colunas, exceto
name
, o que significa que você só precisa listar as colunas que deseja uma vez e é mais fácil combiná-las visualmente - continue adicionando when
cláusulas; e você não precisa da contagem de linhas: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