1

我需要将列转换为行并获得其平均值。

例如我有这张表:

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

我怎样才能实现它?感谢您的帮助。

4

1 回答 1

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

但既然你不是,你可以假装它。改编自本网站

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 个,你应该重新审视数据模型)。这两个decode语句使用生成的数字来匹配列名和值 - 自行运行内部选择以查看其外观。

如果不使用动态 SQL,您将无法避免列出列 - 只列出一次真实unpivot的 10g 版本,但两次使用假的 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
于 2012-07-25T08:29:47.850 回答