是否有可能在Oracle中有条件地透视不同数据类型的列?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了是否有可能在Oracle中有条件地透视不同数据类型的列?相关的知识,希望对你有一定的参考价值。
使用Oracle 12c。我有一个查询,该查询返回我需要的所有数据,但是它分为多行。我正在尝试使用数据透视表将n行中的数据合并为1行,将2列中的n个唯一值集转换为n列,有条件地从一组列中选择哪一列对n个转置后的每一个使用值列。我正在努力找出这是否可行或无法实现。
以下是查询返回内容的简化示例:
| ID | Inst_Created | Inst_Modified | Inst_Group | Inst_Prop | VAL_INT | VAL_REAL | VAL_STR |
+----+--------------+---------------+------------+-----------+---------+----------+---------+
| 01 | 1571954537 | 1571954537 | GenGroup1 | IntProp1 | 0 | (null) | (null) |
| 01 | 1571954537 | 1571954537 | GenGroup1 | RealProp2 | (null) | 12.34567 | (null) |
| 01 | 1571954537 | 1571954537 | GenGroup1 | RealProp3 | (null) | 123.4567 | (null) |
| 01 | 1571954537 | 1571954537 | GenGroup1 | StrProp4 | (null) | (null) | dirpath |
| 01 | 1571954537 | 1577754537 | GenGroup2 | IntProp5 | 1337 | (null) | (null) |
| 01 | 1571954537 | 1577754537 | GenGroup2 | RealProp6 | (null) | 13.37 | (null) |
| 01 | 1570054537 | 1570854537 | GenGroup3 | StrProp7 | (null) | (null) | testing |
| 01 | 1570054537 | 1570854537 | GenGroup3 | StrProp8 | (null) | (null) | valid |
| 02 | 1571954540 | 1571954540 | GenGroup1 | IntProp1 | 1 | (null) | (null) |
| 02 | 1571954540 | 1571954540 | GenGroup1 | RealProp2 | (null) | 12.34568 | (null) |
| 02 | 1571954540 | 1571954540 | GenGroup1 | RealProp3 | (null) | 123.4568 | (null) |
| 02 | 1571954540 | 1571954540 | GenGroup1 | StrProp4 | (null) | (null) | dirpat2 |
| 02 | 1571954540 | 1577754540 | GenGroup2 | IntProp5 | 1338 | (null) | (null) |
| 02 | 1571954540 | 1577754540 | GenGroup2 | RealProp6 | (null) | 13.38 | (null) |
| 02 | 1570054540 | 1570854540 | GenGroup3 | StrProp7 | (null) | (null) | testin2 |
| 02 | 1570054540 | 1570854540 | GenGroup3 | StrProp8 | (null) | (null) | valid2 |
+----+--------------+---------------+------------+-----------+---------+----------+---------+
Inst_Created和Inst_Modified列是模拟纪元时间戳。 VAL_INT,VAL_REAL和VAL_STR列分别是NUMBER(38,0),FLOAT和VARCHAR2(1024)数据类型。对于任何给定的行,只有三列VAL_ *列为非空;您可以通过Inst_Group,Inst_Prop列知道这是哪三个。
以下是我试图通过使用数据透视表进行简化的示例:
| ID | Earliest_Created | Latest_Modified | G1P1_Int | G1P2_Real | G1P3_Real | G1P4_Str | G2P5_Int | G2P6_Real | G3P7_Str | G3P8_Str |
+----+------------------+-----------------+----------+-----------+-----------+----------+----------+-----------+----------+----------+
| 01 | 1570054537 | 1577754537 | 0 | 12.34567 | 123.4567 | dirpath | 1337 | 13.37 | testing | valid |
| 02 | 1570054540 | 1579954540 | 1 | 12.34568 | 123.4568 | dirpat2 | 1338 | 13.38 | testin2 | valid2 |
+----+------------------+-----------------+----------+-----------+-----------+----------+----------+-----------+----------+----------+
我已经弄清楚了如何在重命名列的同时使用ivot_for_clause和pivot_in_clause子句将(Inst_Group,Inst_Prop)值转换为列。我正在努力弄清的是如何将值放入转置的列中,它们是正确的数据类型。
我以前曾尝试在查询中使用LISTAGG函数,将所有VAL_ *值都强制转换为varchar2,因此VAL值只有一列。由于尝试将每个转置的列设置为正确的原始数据类型时遇到问题,并且由于性能下降,所有这些似乎都在造成该问题,因此我放弃了该方法。
您可以使用conditional aggreagation
实现它:
Select ID, EARLIEST_CREATED, LATEST_MODIFIED,
MAX(CASE WHEN INST_GROUP = 'GenGroup1' and INST_PROP1 = 'IntProp1' THEN VAL_INT END) AS G1P1_INT,
MAX(CASE WHEN INST_GROUP = 'GenGroup1' and INST_PROP1 = 'RealProp2' THEN VAL_REAL END) AS G1P2_REAL,
...
..
.
From your_table
Group by ID, EARLIEST_CREATED, LATEST_MODIFIED;
干杯!
以上是关于是否有可能在Oracle中有条件地透视不同数据类型的列?的主要内容,如果未能解决你的问题,请参考以下文章