2012-07-25 98 views
1

我需要将列转为行并获取其平均值。Oracle10G SQL:将列转为行

例如,我有这个表:

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

可能重复的[将行转换为oracle10g中的列](http://stackoverflow.com/questions/3512140/convert-row-into-columns-in- oracle10g) – Ollie 2012-07-26 12:19:50

+0

[Oracle Columns to Rows]的可能重复(http://stackoverflow.com/questions/867737/oracle-columns-to-rows) – 2012-07-27 14:41:38

回答

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所有列,这意味着你只需要列出你想一次列,它更容易直观地匹配起来 - 只是不断增加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