在 Oracle 中使用动态列进行透视
Posted
技术标签:
【中文标题】在 Oracle 中使用动态列进行透视【英文标题】:Pivot with Dynamic Columns in Oracle 【发布时间】:2020-09-30 12:22:03 【问题描述】:我是新的 oracle 数据库,我有一个如下表
ID Passengers Age Eligible
123456 Ben 65 Yes
123456 Mary 58 Yes
123458 Stephanie 37 Yes
123458 Aaron 32 Yes
123458 Caroline 18 No
我想得到动态列名为 Age1、Age2、Age3 等的结果,如下所示
ID Age1 Age2 Age3
123456 65 58 NULL
123458 37 32 18
这可以通过SQL Server
中的 STUFF 和 Dynamic Pivot 来实现,但我不知道如何在Oracle
中实现这一点
谁能指导我如何在Oracle
动态地做到这一点
【问题讨论】:
SO中有很多例子,其中一个有多种方式是***.com/a/31420487/13878023..你检查并卡在某个地方了吗?另一个简单的,你也可以关注...***.com/questions/50259728/oracle-dynamic-pivoting @Sujitmohanty30 我已经解决了您在此处提到的问题,动态列名都来自列值,但我希望将相同的列名拆分为三个,例如。年龄为 Age1,Age2,Age3,因为我是 Oracle 的新手,所以在 Oracle 中这样做对我来说很困难。我也希望结果集为表格 我明白了,这没问题。一个问题是为什么结果中缺少Passengers
?由于时间限制,我只能提供查询,然后可以将其转换为PLSQL。或者只是等待,我相信你很快就会得到解决方案:)
【参考方案1】:
SYS_REFCURSOR
在存储函数中(例如使用 PL/SQL 而不是直接使用 SQL)可能用于获取动态生成的结果集(例如。Dynamic Pivot)。在这种情况下,会生成一个用于条件聚合的字符串:
CREATE OR REPLACE FUNCTION get_passengers_rs RETURN SYS_REFCURSOR IS
v_recordset SYS_REFCURSOR;
v_sql VARCHAR2(32767);
v_str VARCHAR2(32767);
BEGIN
SELECT LISTAGG('MAX(CASE WHEN rn = '||lvl||' THEN age||''(''||passengers||'')'' END)
AS "Age'||lvl||'"' ,',') WITHIN GROUP (ORDER BY 0)
INTO v_str
FROM ( SELECT level AS lvl
FROM dual
CONNECT BY level <= (SELECT MAX(COUNT(*)) FROM t GROUP BY ID ) ) t;
v_sql :=
'SELECT ID, '|| v_str ||'
FROM
(
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY 0) AS rn
FROM t
)
GROUP BY ID';
OPEN v_recordset FOR v_sql;
RETURN v_recordset;
END;
我还添加了乘客的姓名,以便很好地区分每个数据。
然后运行以下代码:
VAR rc REFCURSOR
EXEC :rc := get_passengers_rs;
PRINT rc
从 SQL Developer 的命令行查看预期的结果集。
以上代码为当前存在的数据生成这个SQL字符串(v_sql)
SELECT ID, MAX(CASE WHEN rn = 1 THEN age||'('||passengers||')' END) AS "Age1",
MAX(CASE WHEN rn = 2 THEN age||'('||passengers||')' END) AS "Age2",
MAX(CASE WHEN rn = 3 THEN age||'('||passengers||')' END) AS "Age3"
FROM
(
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY 0) AS rn
FROM t
)
GROUP BY ID
产生
ID Age1 Age2 Age3
123456 58(Marie) 65(Ben)
123458 32(Aaron) 18(Caroline) 37(Stephanie)
作为结果集。
【讨论】:
以上是关于在 Oracle 中使用动态列进行透视的主要内容,如果未能解决你的问题,请参考以下文章
使用 Sql Developer Oracle 的动态数据透视查询