在 oracle 中用 Unpivot 替换 union all

Posted

技术标签:

【中文标题】在 oracle 中用 Unpivot 替换 union all【英文标题】:Replacing union all with Unpivot in oracle 【发布时间】:2021-05-16 07:53:49 【问题描述】:

我有以下查询:

SELECT COL1,ABC AS COL2,'1' AS SEQ,'GRP 10' AS GRP_NAME,'ABC' AS INPUT_COL_NAME,'NEW1' AS OUTPUT_COL_NAME FROM TABLE1
UNION ALL
SELECT COL1,MNO AS COL2,'2' AS SEQ,'GRP 10' AS GRP_NAME,'MNO' AS INPUT_COL_NAME,'NEW2' AS OUTPUT_COL_NAME FROM TABLE1
UNION ALL
SELECT COL1,XYZ AS COL2,'3' AS SEQ,'GRP 10' AS GRP_NAME,'XYZ' AS INPUT_COL_NAME,'NEW3' AS OUTPUT_COL_NAME FROM TABLE1

输入表数据:

SELECT COL1,COL2 FROM TABLE1
COL1 ABC MNO XYZ
1 0 20 100
2 15 50 150

输出是:

COL1 COL2 SEQ GRP_NAME INPUT_COL_NAME OUTPUT_COL_NAME
1 0 1 GRP_NEW ABC NEW1
2 15 1 GRP_NEW ABC NEW1
1 20 2 GRP_NEW MNO NEW2
2 50 2 GRP_NEW MNO NEW2
1 100 3 GRP_NEW XYZ NEW3
2 150 3 GRP_NEW XYZ NEW3

上面的查询可以转化为 PIVOT 查询吗?生成相同的输出。

【问题讨论】:

【参考方案1】:

你想要UNPIVOT(而不是PIVOT):

SELECT col1,
       col2,
       seq,
       'GRP_NEW' AS grp_name,
       input_col_name,
       output_col_name
FROM   table1
UNPIVOT (
  input_col_name FOR ( col2, seq, output_col_name ) IN (
    abc AS ( 'ABC', 1, 'NEW1' ),
    mno AS ( 'MNO', 2, 'NEW2' ),
    xyz AS ( 'XYZ', 3, 'NEW3' )
  )
)
ORDER BY seq, col1

其中,对于样本数据:

CREATE TABLE table1 ( COL1, ABC, MNO, XYZ ) AS
SELECT 1,  0, 20, 100 FROM DUAL UNION ALL
SELECT 2, 15, 50, 150 FROM DUAL

输出:

COL1 COL2 SEQ GRP_NAME INPUT_COL_NAME OUTPUT_COL_NAME
1 ABC 1 GRP_NEW 0 NEW1
2 ABC 1 GRP_NEW 15 NEW1
1 MNO 2 GRP_NEW 20 NEW2
2 MNO 2 GRP_NEW 50 NEW2
1 XYZ 3 GRP_NEW 100 NEW3
2 XYZ 3 GRP_NEW 150 NEW3

db小提琴here

【讨论】:

以上是关于在 oracle 中用 Unpivot 替换 union all的主要内容,如果未能解决你的问题,请参考以下文章

Oracle - 在选择查询中用 OEM_sqlplus_input_finished 替换 &

在 oracle SP 中用更大的数据类型替换 varchar2

oracle unpivot 多列到多列

Oracle 11g - Unpivot

对于以下场景,如何在 oracle sql 中执行类似 unpivot 的操作?

unpivot 和 oracle 对象的问题