将多行转换为一行

Posted

技术标签:

【中文标题】将多行转换为一行【英文标题】:convert multiple rows into one row 【发布时间】:2020-05-04 13:48:46 【问题描述】:

我有这张桌子:

id  operation  phone_number  package
1   Add        991           super_package no. 2    
1   Delete     991           super_package no. 1
2   Add        902           super_package no. 3    
2   Delete     902           super_package no. 1
2   Add        988           super_package no. 5    
2   Delete     988           super_package no. 2

我想查询该表,使其看起来像这样:

id  phone_number  new_pkg              old_pkg
1   991           super_package no. 2  super_package no. 1
2   902           super_package no. 3  super_package no. 1
3   988           super_package no. 5  super_package no. 2

如果操作是add,new_pkg 值设置为package 列的值,如果操作是delete,old_pkg 值设置为package 列的值。

我能做的就是这样:

SELECT id,phone_number  , LISTAGG(package, ', ') WITHIN GROUP (ORDER BY id) AS new_pkg
FROM table GROUP BY id;

结果

id phone_number  new_pkg  
1  991           super_package no. 2, super_package no. 1
2  902           super_package no. 3, super_package no. 1
3  988           super_package no. 5, super_package no. 2

有什么帮助吗?

【问题讨论】:

您的输出中的 id=3 来自哪里?您在输入中是否有错字 - 最后两行的 id=3,而不是 2? 【参考方案1】:

我想你想要条件聚合:

SELECT id, phone_number,
       MAX(CASE WHEN operation = 'ADD' THEN package END) as new_pkg,
       MAX(CASE WHEN operation = 'DELETE' THEN package END) as old_pkg
FROM table
GROUP BY id, phone_number;

【讨论】:

【参考方案2】:

你需要的操作叫做pivoting。 Oracle 为此添加了 pivot 运算符,早在 11.1 版本。

with
  sample_data (id, operation, phone_number, package) as (
    select 1, 'Add'   , 991, 'super_package no. 2' from dual union all    
    select 1, 'Delete', 991, 'super_package no. 1' from dual union all
    select 2, 'Add'   , 902, 'super_package no. 3' from dual union all
    select 2, 'Delete', 902, 'super_package no. 1' from dual union all
    select 3, 'Add'   , 988, 'super_package no. 5' from dual union all
    select 3, 'Delete', 988, 'super_package no. 2' from dual
  )
-- End of sample data (for testing only, not part of the query).
-- Use your real table name in the FROM clause below.
select id, phone_number, new_pkg, old_pkg
from   sample_data
pivot  (min(package) for operation in ('Add' as new_pkg, 'Delete' as old_pkg))
order  by id  --  if needed
;

ID  PHONE_NUMBER  NEW_PKG              OLD_PKG            
--  ------------  -------------------  -------------------
 1           991  super_package no. 2  super_package no. 1
 2           902  super_package no. 3  super_package no. 1
 3           988  super_package no. 5  super_package no. 2

【讨论】:

效果很好:dbfiddle here

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

将多行文件转换为一行

ORACLE——将多行文本数据转换成一行

将单行转换为多行 Bigquery SQL

使用 Linux 工具将多行 csv 转换为单行

如何用熊猫将多行组合成一行[重复]

MySQL.之 一行内容转换多行