2012-07-25 87 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