将行数据拆分为列

Posted

技术标签:

【中文标题】将行数据拆分为列【英文标题】:Split rows data to columns 【发布时间】:2009-02-19 08:57:01 【问题描述】:

我有一个结构简单的表格:

user_id、月份、余额、余额类型

我想为每个用户显示每月选择的余额类型:

user_id、月份、balance_1、balance_2、balance_3、balance_...

所以从数据来看:

ROW user_id month balance balance_type    
1   5667    09   20         2068
2   5667    08   23         2068
3   5667    07   21         2068
4   5667    06   19         2068
5   5667    10   22         2068
6   5667    09   20         2069
7   5667    08   23         2069
8   5667    06   19         2069
9   5667    07   21         2069
10  5667    10   22         2069
11  5667    09   4199       2114
12  5667    06   4329       2114
13  5667    08   4365       2114    
14  5667    10   4172,88    2114    
15  5667    07   4000       2114    
16  5667    10   572,1      6062    
17  5667    08   598,44     6062    
18  5667    07   548,4      6062    
19  5667    06   593,51     6062    
20  5667    09   575,69     6062    

我会得到例如第 09 个月的数据:

user_id, month, balance_1, balance_2, balance_3, balance_4    
5667      09      20        20            4199    575,69

在 SQL 或/和 PL/SQL 中对此的最佳解决方案是什么?

【问题讨论】:

如果您使用 11G,请参阅 PIVOT 子句:download.oracle.com/docs/cd/B28359_01/server.111/b28313/… 如果使用 9i 或 10g,请参阅:asktom.oracle.com/pls/asktom/…。 【参考方案1】:

如果您有固定数量的余额类型并且 (user_id, month, balance_type) 是唯一的元组,那么您可以为每个余额类型执行一个内联子查询。例如:

select user_id, month, 
(select balance from balance_table bt where bt.user_id = user_id and bt.month = month and bt.balance_type = '1'),
(select balance from balance_table bt where bt.user_id = user_id and bt.month = month and bt.balance_type = '2') .....
from balance_table

如果可能有多个行具有相同的 balance_type、month 和 user_id,那么您可能需要使用 pivot 命令来为每个组添加余额,这在 SQL Server 和 Oracle(仅限 11g)中都存在。比如说你有 balance_types 1,2,3,4

select * from balance_table pivot (select sum(balance) for balance_type IN (1,2,3,4))

如果你事先不知道有多少 balance_types,那么我认为动态生成的 sql 是唯一的方法,在这种情况下你应该使用例如 Oracle 的 DBMS_SQL PL/SQL 包。

【讨论】:

【参考方案2】:

如果这是一次性要求,我可以建议一个 hack。在 user_id 和 month 上使用多个自连接(您需要的连接数量与余额类型一样多)。

select a.user_id, a.month, a.balance balance_1, b.balance balance_2, c.balance balance_3...
from mytable a, mytable b, mytable c....
where 
a.month = 9 and
a.balance_type=1 and
a.user_id = b.user_id and
a.month = b.month and
b.balance_type=2 and
b.user_id = c.user_id and 
c.user_id = d.user_id and
c.balance_type=3....

此解决方案可能不是最好的,但作为一次性黑客的魅力就像一个魅力。

【讨论】:

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

使RegEx组将行拆分为列

将行数据转换为列

SQL Server 将行数据转换为列标题

在 Tableau 中反透视数据 将行转换为列

这是一个员工数据,我想使用数据透视将行数据转换为列

如何将行数据查询为列?