将数据透视到新的列名 - Oracle SQL
Posted
技术标签:
【中文标题】将数据透视到新的列名 - Oracle SQL【英文标题】:Pivot Data into New Column Names - Oracle SQL 【发布时间】:2021-04-21 20:46:55 【问题描述】:在 Oracle SQL 中工作,我有以下数据集:
我的目标是将它放入一个看起来像这样的数据集,我假设我将不得不使用某种形式的数据透视函数,但我不确定如何创建新的列名'在同一步骤中尚不存在:
我只提供了我的全部数据集的一个示例,会有大量 INDIV_ID 记录具有不同数量的可能购买日期(即,并非每个 INDIV_ID 都会有 10 个购买日期。有些可能有更多,有些可能有更少)
提前谢谢你, 尼克
【问题讨论】:
您开始使用的结构适用于不同数量的日期。您的目标结构不是。这是一种 SQL 反模式,这在 SQL 中是不正确的。 SQL 不是 Excel,坚持规范化(原始)数据结构,这是专为 SQL 使用而设计的。 【参考方案1】:如果您知道所需的列数,则可以这样做:
select indiv_id,
max(case when seqnum = 1 then prch_dt end) as dt_1,
max(case when seqnum = 2 then prch_dt end) as dt_2,
. . .
from (select t.*,
row_number() over (partition by indiv_id order by prch_dt) as seqnum
from t
) t
group by indiv_id;
如果不知道列数,则需要使用动态SQL——相当麻烦。
或者,您可以将值聚合到单个分隔字符串中:
select indiv_id,
list_agg(prch_dt, ',') within group (order by prch_dt)
from (select t.*,
row_number() over (partition by indiv_id order by prch_dt) as seqnum
from t
) t
group by indiv_id;
【讨论】:
【参考方案2】:您可以使用条件聚合的方式创建一个选择语句字符串来旋转这些列,同时通过使用ROW_NUMBER()
函数对每个单独的日期进行枚举,以便动态分配不同的整数值,即使存在相等的日期存储函数中的值,该函数返回 SYS_REFCURSOR
类型的值,例如
CREATE OR REPLACE FUNCTION Fn_Pivot_Table RETURN SYS_REFCURSOR IS
v_recordset SYS_REFCURSOR;
v_sql VARCHAR2(32767);
v_cols VARCHAR2(32767);
BEGIN
SELECT LISTAGG( 'MAX(CASE WHEN rn = '||rn||' THEN prch_dt END ) AS "Date_'||rn||'"' , ',')
WITHIN GROUP ( ORDER BY rn )
INTO v_cols
FROM ( SELECT prch_dt,ROW_NUMBER() OVER (PARTITION BY indiv_id ORDER BY prch_dt) AS rn FROM t );
v_sql :='SELECT indiv_id,'|| v_cols ||
' FROM ( SELECT t.*,ROW_NUMBER() OVER (PARTITION BY indiv_id ORDER BY prch_dt) AS rn FROM t )
GROUP BY indiv_id';
OPEN v_recordset FOR v_sql;
RETURN v_recordset;
END;
/
其中t
表示您需要对其进行透视的表购买日期值。
然后从 SQL Developer 的控制台调用该函数
SQL> DECLARE
result SYS_REFCURSOR;
BEGIN
:result := Fn_Pivot_Table;
END;
/
SQL> PRINT result;
【讨论】:
有趣,这似乎是这工作的第一部分。但是当我尝试从 SQL Dev 的控制台调用该函数时,我得到了未知的命令错误 嗨@Ciccotelli412,你遇到了什么错误?以上是关于将数据透视到新的列名 - Oracle SQL的主要内容,如果未能解决你的问题,请参考以下文章