Oracle SQL:将多列转置为行

Posted

技术标签:

【中文标题】Oracle SQL:将多列转置为行【英文标题】:Oracle SQL: Transpose Multiple Columns to Row 【发布时间】:2018-10-26 11:48:57 【问题描述】:

将多列转置为行的最佳方法

给定:

            A    B  C   D   E   F   G 
    FYQ1    11  10  8   6   1   0   0
    FYQ2    11  10  8   7   2   0   0
    FYQ3    11  11  11  10  5   4   0
    FYQ4    11  11  11  10  5   4   0

必填:

        FYQ1 FYQ2 FYQ3 FYQ4
    A   11   11     11  11
    B   10   10     11  11
    C   8    8      11  11
    D   6    7      10  10
    E   1    2      5   5
    F   0    0      4   4
    G   0    0      0   0 

【问题讨论】:

为什么不想使用聚合函数呢?您使用的是什么版本的 Oracle? 12c,我们可以使用聚合吗??, 【参考方案1】:

我看到你编辑了你的问题。

您可以尝试将条件聚合函数与UNION ALL一起使用

CREATE TABLE T(
   Name varchar(50),
   A int,
   B int,
   C int,
   D int,
   E int,
   F int,
   G int
);


INSERT INTO T VALUES ('FYQ1',11,10,8 ,6,1,0,0);
INSERT INTO T VALUES ('FYQ2',11,10,8 ,7,2,0,0);
INSERT INTO T VALUES ('FYQ3',11,11,11,10,5,4,0);
INSERT INTO T VALUES ('FYQ4',11,11,11,10,5,4,0);

查询 1

SELECT 'A' as " ",
        MAX(CASE WHEN  NAME = 'FYQ1' THEN A END) FYQ1,
        MAX(CASE WHEN  NAME = 'FYQ2' THEN A END) FYQ2,
        MAX(CASE WHEN  NAME = 'FYQ3' THEN A END) FYQ3,
        MAX(CASE WHEN  NAME = 'FYQ4' THEN A END) FYQ4
FROM T
UNION ALL
SELECT 'C',
        MAX(CASE WHEN  NAME = 'FYQ1' THEN C END),
        MAX(CASE WHEN  NAME = 'FYQ2' THEN C END),
        MAX(CASE WHEN  NAME = 'FYQ3' THEN C END),
        MAX(CASE WHEN  NAME = 'FYQ4' THEN C END)
FROM T
UNION ALL
SELECT 'D',
        MAX(CASE WHEN  NAME = 'FYQ1' THEN D END),
        MAX(CASE WHEN  NAME = 'FYQ2' THEN D END),
        MAX(CASE WHEN  NAME = 'FYQ3' THEN D END),
        MAX(CASE WHEN  NAME = 'FYQ4' THEN D END)
FROM T
UNION ALL
SELECT 'E',
        MAX(CASE WHEN  NAME = 'FYQ1' THEN E END),
        MAX(CASE WHEN  NAME = 'FYQ2' THEN E END),
        MAX(CASE WHEN  NAME = 'FYQ3' THEN E END),
        MAX(CASE WHEN  NAME = 'FYQ4' THEN E END)
FROM T
UNION ALL
SELECT 'F',
        MAX(CASE WHEN  NAME = 'FYQ1' THEN F END),
        MAX(CASE WHEN  NAME = 'FYQ2' THEN F END),
        MAX(CASE WHEN  NAME = 'FYQ3' THEN F END),
        MAX(CASE WHEN  NAME = 'FYQ4' THEN F END)
FROM T
UNION ALL
SELECT 'G',
        MAX(CASE WHEN  NAME = 'FYQ1' THEN G END),
        MAX(CASE WHEN  NAME = 'FYQ2' THEN G END),
        MAX(CASE WHEN  NAME = 'FYQ3' THEN G END),
        MAX(CASE WHEN  NAME = 'FYQ4' THEN G END)
FROM T

Results

|   | FYQ1 | FYQ2 | FYQ3 | FYQ4 |
|---|------|------|------|------|
| A |   11 |   11 |   11 |   11 |
| C |    8 |    8 |   11 |   11 |
| D |    6 |    7 |   10 |   10 |
| E |    1 |    2 |    5 |    5 |
| F |    0 |    0 |    4 |    4 |
| G |    0 |    0 |    0 |    0 |

【讨论】:

我们可以使用 WITH 子句优化它吗?只需执行一次所有 T 表计算。【参考方案2】:

您可以使用 unpivot 和 pivot,我分享示例。


CREATE TABLE T(
   Name varchar(50),
   A int,
   B int,
   C int,
   D int,
   E int,
   F int,
   G int
);


INSERT INTO T VALUES ('FYQ1',11,10,8 ,6,1,0,0);
INSERT INTO T VALUES ('FYQ2',11,10,8 ,7,2,0,0);
INSERT INTO T VALUES ('FYQ3',11,11,11,10,5,4,0);
INSERT INTO T VALUES ('FYQ4',11,11,11,10,5,4,0);

SELECT   words,
         fyq1,
         fyq2,
         fyq3,
         fyq4
FROM     (
                SELECT name,
                       fyq1 AS words,
                       value
                FROM   (
                              SELECT                                                 *
                              FROM   t) unpivot ( (value) FOR (fyq1,fyq2,fyq3,fyq4) IN (a,
                                                                                        b,
                                                                                        c,
                                                                                        d,
                                                                                        e,
                                                                                        f,
                                                                                        g) )) pivot( SUM(value) FOR name IN ('FYQ1' AS fyq1,
                                                                                                                             'FYQ2' AS fyq2,
                                                                                                                             'FYQ3' AS fyq3,
                                                                                                                             'FYQ4' AS fyq4) )
ORDER BY words;

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。

以上是关于Oracle SQL:将多列转置为行的主要内容,如果未能解决你的问题,请参考以下文章

SQL 将多列转置为行

oracle sql 11G中如何将列转置为行

oracle pl sql中如何将列数据转置为行

Postgres 表选择多列并将结果(列)动态转换为行 - 将列转置为行

将列转置为行 SQL Server

在 SQL 中将行转置为列标题