我需要将列转换为行并获得平均值。
例如我有这张表:
Name Math Science Computer
---- ---- ------- --------
Ted 90 89 95
Zed 99 98 98
Fed 85 75 90
输出应为:
Subject Average
------- -------
Math 88
Science 87.33
Computer 94.33
我怎样才能实现它?谢谢你的帮助。
答案 0 :(得分:2)
如果您使用的是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
但既然你不是,那你可以假装它。适应this 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
在这两种情况下,内部select
正在将行转换为列;在10克你只需要自己做。 SELECT ... CONNECT BY ...
只生成一个虚拟值列表,这必须足以覆盖您要转换为行的列数(如果您确实有1000个,则应该重新访问数据模型)。两个decode
语句使用生成的数字来匹配列名和值 - 单独运行内部选择以查看它的外观。
不依赖于动态SQL,你无法摆脱列表 - 只有一次使用真实的unpivot
,而是两次使用假的10g版本,你必须确保它们匹配正确,并且行号生成器正在生成足够的值。 (太多了,你可能会得到奇怪的结果,但是因为任何额外的值在这里都是null而你正在使用avg
,在这种情况下它并不重要;只是作为一个完整性检查你应该做的它完全匹配。)
或者是另一个版本,基于您总是想要除name
之外的所有列,这意味着您只需要列出您想要的列一次,并且更容易在视觉上匹配它们 - 只需继续添加{{1条款;而且你不需要行数:
when