将行转换为列 Oracle

Posted

技术标签:

【中文标题】将行转换为列 Oracle【英文标题】:Convert rows into columns Oracle 【发布时间】:2012-06-21 12:16:21 【问题描述】:

这个问题已经被问了好几次,也被回答了很多次,但这次不一样,因为:

    这是在 Oracle 11g 中 - 我看到的其他示例是在带有 StUFF 函数的 SQL Server 中 这需要加入 2 个表来获取信息

让我解释一下

这是包含字段名称和 File_ID 的表

CREATE TABLE RESPONSE_METADATA
(
  FILE_ID        NUMBER(10)                     NOT NULL,
  FIELD_NUMBER   NUMBER(4)                      NOT NULL,
  FIELD_NAME     VARCHAR2(50 BYTE)              NOT NULL,
  FIELD_TYPE     VARCHAR2(50 BYTE)              NOT NULL
);

这是一个表格,保存着每个文件的记录,但记录是分开的。

CREATE TABLE RESPONSE_DETAILS
(
  FILE_ID        NUMBER(10),
  REC_FLD_1      VARCHAR2(300 BYTE),
  REC_FLD_2      VARCHAR2(300 BYTE),
  REC_FLD_3      VARCHAR2(300 BYTE),
  REC_FLD_4      VARCHAR2(300 BYTE),
  REC_FLD_5      VARCHAR2(300 BYTE),
  REC_FLD_6      VARCHAR2(300 BYTE),
  REC_FLD_7      VARCHAR2(300 BYTE),
  REC_FLD_8      VARCHAR2(300 BYTE),
  REC_FLD_9      VARCHAR2(300 BYTE),
  REC_FLD_10     VARCHAR2(300 BYTE),
  REC_FLD_11     VARCHAR2(300 BYTE),
  REC_FLD_12     VARCHAR2(300 BYTE),
  REC_FLD_13     VARCHAR2(300 BYTE),
  REC_FLD_14     VARCHAR2(300 BYTE),
  REC_FLD_15     VARCHAR2(300 BYTE),
  REC_FLD_16     VARCHAR2(300 BYTE),
  REC_FLD_17     VARCHAR2(300 BYTE),
  REC_FLD_18     VARCHAR2(300 BYTE),
  REC_FLD_19     VARCHAR2(300 BYTE),
  REC_FLD_20     VARCHAR2(300 BYTE)
);

插入数据

INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (1,1,'REC_ID','NUMBER');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (1,2,'EMAIL','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (1,3,'CAMP','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (1,4,'ACTION','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (1,5,'DESC','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (1,6,'TIME','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (1,7,'CHANNEL','NUMBER');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (1,8,'STATUS','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (1,9,'DI_CODE','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (1,10,'CUSTOM','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (2,1,'REC_ID','NUMBER');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (2,2,'EMAIL','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (2,3,'CAMP','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (2,4,'ACTION','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (2,5,'DESC','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (3,1,'REC_ID','NUMBER');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (3,2,'EMAIL','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (3,3,'CAMP','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (4,1,'REC_ID','NUMBER');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (4,2,'ORGN','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (4,3,'LOGOS','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (4,4,'ACTN','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (4,5,'BLANK1','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (4,6,'ALERT_ID','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (4,7,'DEVNUM','NUMBER');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (4,8,'RES_CODE','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (4,9,'STRAT_ID','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (4,10,'COMP_FLAG','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (4,11,'AUDLOG','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (4,12,'STARTTIME','VARCHAR2');
INSERT INTO RESPONSE_METADATA (FILE_ID, FIELD_NUMBER, FIELD_NAME, FIELD_TYPE) VALUES (4,13,'DURATION','VARCHAR2');

INSERT INTO RESPONSE_DETAILS (FILE_ID, REC_FLD_1, REC_FLD_2, REC_FLD_3, REC_FLD_4, REC_FLD_5, REC_FLD_6, REC_FLD_7, REC_FLD_8, REC_FLD_9, REC_FLD_10, REC_FLD_11, REC_FLD_12, REC_FLD_13, REC_FLD_14, REC_FLD_15, REC_FLD_16, REC_FLD_17, REC_FLD_18, REC_FLD_19, REC_FLD_20)VALUES (8,'67537','Line','','81433','1','15062012','DELIVERED','67537','','','','','','','','','','','','');
INSERT INTO RESPONSE_DETAILS (FILE_ID, REC_FLD_1, REC_FLD_2, REC_FLD_3, REC_FLD_4, REC_FLD_5, REC_FLD_6, REC_FLD_7, REC_FLD_8, REC_FLD_9, REC_FLD_10, REC_FLD_11, REC_FLD_12, REC_FLD_13, REC_FLD_14, REC_FLD_15, REC_FLD_16, REC_FLD_17, REC_FLD_18, REC_FLD_19, REC_FLD_20)VALUES (8,'67551','Line','','81430','1','15062012','DELIVERED','67551','','','','','','','','','','','','');
INSERT INTO RESPONSE_DETAILS (FILE_ID, REC_FLD_1, REC_FLD_2, REC_FLD_3, REC_FLD_4, REC_FLD_5, REC_FLD_6, REC_FLD_7, REC_FLD_8, REC_FLD_9, REC_FLD_10, REC_FLD_11, REC_FLD_12, REC_FLD_13, REC_FLD_14, REC_FLD_15, REC_FLD_16, REC_FLD_17, REC_FLD_18, REC_FLD_19, REC_FLD_20)VALUES (8,'67579','Line','','81403','1','15062012','DELIVERED','67579','','','','','','','','','','','','');
INSERT INTO RESPONSE_DETAILS (FILE_ID, REC_FLD_1, REC_FLD_2, REC_FLD_3, REC_FLD_4, REC_FLD_5, REC_FLD_6, REC_FLD_7, REC_FLD_8, REC_FLD_9, REC_FLD_10, REC_FLD_11, REC_FLD_12, REC_FLD_13, REC_FLD_14, REC_FLD_15, REC_FLD_16, REC_FLD_17, REC_FLD_18, REC_FLD_19, REC_FLD_20)VALUES (8,'67593','Line','','81452','1','15062012','DELIVERED','67593','','','','','','','','','','','','');
INSERT INTO RESPONSE_DETAILS (FILE_ID, REC_FLD_1, REC_FLD_2, REC_FLD_3, REC_FLD_4, REC_FLD_5, REC_FLD_6, REC_FLD_7, REC_FLD_8, REC_FLD_9, REC_FLD_10, REC_FLD_11, REC_FLD_12, REC_FLD_13, REC_FLD_14, REC_FLD_15, REC_FLD_16, REC_FLD_17, REC_FLD_18, REC_FLD_19, REC_FLD_20)VALUES (8,'67607','Line','','81453','1','15062012','DELIVERED','67607','','','','','','','','','','','','');
INSERT INTO RESPONSE_DETAILS (FILE_ID, REC_FLD_1, REC_FLD_2, REC_FLD_3, REC_FLD_4, REC_FLD_5, REC_FLD_6, REC_FLD_7, REC_FLD_8, REC_FLD_9, REC_FLD_10, REC_FLD_11, REC_FLD_12, REC_FLD_13, REC_FLD_14, REC_FLD_15, REC_FLD_16, REC_FLD_17, REC_FLD_18, REC_FLD_19, REC_FLD_20)VALUES (4,'28072','16','1','189325','','ins/code.com/20120621','6551','WID ','VOLN ','N',';B10100','41061.6740856481','14','','','','','','','');
INSERT INTO RESPONSE_DETAILS (FILE_ID, REC_FLD_1, REC_FLD_2, REC_FLD_3, REC_FLD_4, REC_FLD_5, REC_FLD_6, REC_FLD_7, REC_FLD_8, REC_FLD_9, REC_FLD_10, REC_FLD_11, REC_FLD_12, REC_FLD_13, REC_FLD_14, REC_FLD_15, REC_FLD_16, REC_FLD_17, REC_FLD_18, REC_FLD_19, REC_FLD_20)VALUES (4,'28072','16','1','189325002','','ins/code.com/20120622','6551','CON ','VOLN ','N',';B10100','41061.6978240741','124','','','','','','','');
INSERT INTO RESPONSE_DETAILS (FILE_ID, REC_FLD_1, REC_FLD_2, REC_FLD_3, REC_FLD_4, REC_FLD_5, REC_FLD_6, REC_FLD_7, REC_FLD_8, REC_FLD_9, REC_FLD_10, REC_FLD_11, REC_FLD_12, REC_FLD_13, REC_FLD_14, REC_FLD_15, REC_FLD_16, REC_FLD_17, REC_FLD_18, REC_FLD_19, REC_FLD_20)VALUES (4,'28075','15','30','443433001','','ins/code.com/20120623','5908','AMP ','VOLN ','N',';B10100','41061.6737268519','13','','','','','','','');
INSERT INTO RESPONSE_DETAILS (FILE_ID, REC_FLD_1, REC_FLD_2, REC_FLD_3, REC_FLD_4, REC_FLD_5, REC_FLD_6, REC_FLD_7, REC_FLD_8, REC_FLD_9, REC_FLD_10, REC_FLD_11, REC_FLD_12, REC_FLD_13, REC_FLD_14, REC_FLD_15, REC_FLD_16, REC_FLD_17, REC_FLD_18, REC_FLD_19, REC_FLD_20)VALUES (4,'28075','15','30','4443433','','ins/code.com/20120624','5908','CON ','VOLN ','N',';B10100','41061.6953240741','113','','','','','','','');
INSERT INTO RESPONSE_DETAILS (FILE_ID, REC_FLD_1, REC_FLD_2, REC_FLD_3, REC_FLD_4, REC_FLD_5, REC_FLD_6, REC_FLD_7, REC_FLD_8, REC_FLD_9, REC_FLD_10, REC_FLD_11, REC_FLD_12, REC_FLD_13, REC_FLD_14, REC_FLD_15, REC_FLD_16, REC_FLD_17, REC_FLD_18, REC_FLD_19, REC_FLD_20)VALUES (4,'28078','11','1','2576141','','ins/code.com/20120625','6681','CON ','VOLN ','N',';B10100','41061.6764236111','81','','','','','','','');

现在问题来了

我希望以这种方式查看数据

FILE_ID REC_ID  EMAIL   CAMP    ACTION  DESC    TIME    CHANNEL STATUS  DI_CODE CUSTOM
1   67537   Line        81433   1   15062012    DELIVERED   67537       
1   67551   Line        81430   1   15062012    DELIVERED   67551       
1   67579   Line        81403   1   15062012    DELIVERED   67579       
1   67593   Line        81452   1   15062012    DELIVERED   67593       
1   67607   Line        81453   1   15062012    DELIVERED   67607       


FILE_ID REC_ID  ORGN    LOGOS   ACTN    BLANK1  ALERT_ID            DEVNUM  RES_CODE    STRAT_ID    COMP_FLAG   AUDLOG  STARTTIME   DURATION
4   28072   16  1   189325          ins/code.com/20120621   6551    WID         VOLN    N       ;B10100 1/06/2012 16:10 14
4   28072   16  1   1893250         ins/code.com/20120622   6551    CON         VOLN    N       ;B10100 1/06/2012 16:44 124
4   28075   15  30  4434330         ins/code.com/20120623   5908    AMP         VOLN    N       ;B10100 1/06/2012 16:10 13
4   28075   15  30  4443433         ins/code.com/20120624   5908    CON         VOLN    N       ;B10100 1/06/2012 16:41 113
4   28078   11  1   2576141         ins/code.com/20120625   6681    CON         VOLN    N       ;B10100 1/06/2012 16:14 81

它需要工作的方式是 METADATA 表中的每个 File_ID 都有 FIELD_NUMBER。这些 Filed_Numbers 是 Details 表中的列

我在 Oracle 中尝试了 XML PIVOT,但由于这些列将创建多个节点,因此无法正常工作。

我已经尝试过只是旋转一些东西 - 不起作用。这需要是动态的 - File_ID 可以包含不超过 30 个的任意数量的字段。

这需要是一个存储过程或查询 - 因为我没有构建 ETL 的权限。

【问题讨论】:

你想要的结果的两个块有什么关系?你的测试数据有file_id48,你的输出有14? 如果我理解你的要求,那么你想做某种列名“本地化”(REC_FLD_1->REC_ID)?您必须为每个FILE_ID 使用一个动态查询,但为什么不在客户端执行此操作呢?还是我做错了什么? 【参考方案1】:

试试这个来生成一个脚本:

select 'select '||FILE_ID||' FILE_ID,'||
  ltrim(sys_connect_by_path('REC_FLD_'||FIELD_NUMBER||' "'||FIELD_NAME||'"',','),',')||
  ' from RESPONSE_DETAILS where FILE_ID=' ||FILE_ID||';'
  from (select t.*,count(*) over (partition by FILE_ID) cnt from RESPONSE_METADATA t)
 where cnt=FIELD_NUMBER start with FIELD_NUMBER=1 
connect by prior FILE_ID=FILE_ID and prior FIELD_NUMBER=FIELD_NUMBER-1

添加了双引号,因为某些列名保留了“DESC”,例如

【讨论】:

@PeterLang REC_FLD_1 与 REC_ID 没有任何关系 Nahuel Fouilleul 感谢您的脚本 - 这真是太棒了 - 但是我忘了提 - 我刚刚开始使用 Oracle。我尝试创建 PL/SQL 并运行正在返回的 select 语句,但它没有为我提供 Select 语句的表/结果集。我正在使用蟾蜍。你能帮忙吗?我非常感谢你 - 我已经接近了 - 谢谢你。 感谢您添加双引号 - 为简单起见 - 我缩短了列名 - 在我的表中它实际上称为 Description_Value 感谢@NahuelFouilleul ..它可以完美地按照我的意愿工作。感谢您的帮助。

以上是关于将行转换为列 Oracle的主要内容,如果未能解决你的问题,请参考以下文章

pyspark 将行转换为列

不能从子查询将行转换为列

将行转换为列

根据条件将行转换为列

使用R将行转换为列,将列转换为行

建议将行转换为列的方法