将数据透视到新的列名 - 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的主要内容,如果未能解决你的问题,请参考以下文章

使用数据透视在 Oracle 中显示列名

DB2/SQL怎样把列名变为一列数据

Oracle 11g:取消透视多个列并包含列名

SQL 列名是一个数据并且反透视不起作用

sql 在postgresql中使用动态列名创建交叉表/数据透视表形式的hstore字段

Sql-Server用insert插入多行数据-语法和例子