小编典典

Oracle10G SQL:将列转换为行

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

我该如何实现?感谢您的帮助。


阅读 148

收藏
2021-04-14

共1个答案

小编典典

如果您使用的是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都将行转换为列。在10克中,您只需要自己做即可。在SELECT ... CONNECT BY ...刚刚产生虚值的列表,这必须有足够的覆盖要转换为行(如果你真的有1000,你真的应该重新审视数据模型)的列数。这两个decode语句使用生成的数字来匹配列名和值-
自行运行内部选择以查找外观。

如果不采用动态SQL,就无法不必列出列-
只能使用real列出一次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
2021-04-14