我有一个具有以下结构的表:
cpf ddd phone type origin
11111111111 83 81021111 M SERASA
11111111111 83 87472222 M SERASA
11111111111 83 81023333 M TRANSUNION
11111111111 83 88724444 M TRANSUNION
11111111111 83 87475555 M TRANSUNION
22222222222 43 36271111 F SERASA
22222222222 44 36272222 F SERASA
22222222222 43 36273333 F TRANSUNION
22222222222 43 36284444 F TRANSUNION
33333333333 51 51811111 F SERASA
33333333333 51 56212222 F SERASA
33333333333 51 96213333 M SERASA
我需要"反规范"这个表,所以每个CPF只有一行,如下所示:
CPF DDD_1 PHONE_1 TYPE_1 ORIGIN_1 DDD_2 PHONE_2 TYPE_2 ORIGIN_2 DDD_3 PHONE_3 TYPE_3 ORIGIN_3 DDD_4 PHONE_4 TYPE_4 ORIGIN_4 DDD_5 PHONE_5 TYPE_5 ORIGIN_5
11111111111 83 81021111 M SERASA 83 87472222 M SERASA 83 81023333 M TRANSUNION 83 88724444 M TRANSUNION 83 8747555 M TRANSUNION
22222222222 43 36271111 F SERASA 44 36272222 F SERASA 43 36273333 F TRANSUNION 43 36274444 F TRANSUNION NULL NULL NULL NULL
33333333333 51 51811111 F SERASA 51 56212222 F SERASA 51 96213333 M SERASA NULL NULL NULL NULL NULL NULL NULL NULL
队友建议使用Pivot
+ Unpivot
,但我没有找到如何使用它,因为我没有定义列的字段,也没有& #39; t有聚合(总和,计数等)。
我使用表格本身的连接创建了一些数据(100行),但由于数据量(该表有3300万行),此解决方案无法正常工作。
现在我被卡住了,任何帮助都会受到赞赏。
答案 0 :(得分:1)
如果你自己动手,问题更有可能得到回答。 SO将帮助您解决代码错误和问题,但不是代码编写服务。
那说;它就是这样,我有一个有效的例子......
该示例使用包含在表变量中的示例记录。表变量使共享数据变得更加容易,SQL Fiddle和Stack Data Exchange等服务也是如此。如果您让社区更容易为您提供帮助,您就更有可能得到答案。
示例数据
/* I've used a table variable to make
* sharing the example data easier.
*/
DECLARE @Table TABLE
(
cpf VARCHAR(11),
ddd INT,
phone VARCHAR(10),
[type] VARCHAR(1),
origin VARCHAR(10)
)
;
-- Demo values taken from OP.
INSERT INTO @Table
(
cpf,
ddd,
phone,
[type],
origin
)
VALUES
('11111111111', 83, '87472222', 'M', 'SERASA'),
('11111111111', 83, '81023333', 'M', 'TRANSUNION'),
('11111111111', 83, '88724444', 'M', 'TRANSUNION'),
('11111111111', 83, '87475555', 'M', 'TRANSUNION'),
('22222222222', 43, '36271111', 'F', 'SERASA'),
('22222222222', 44, '36272222', 'F', 'SERASA'),
('22222222222', 43, '36273333', 'F', 'TRANSUNION'),
('22222222222', 43, '36284444', 'F', 'TRANSUNION'),
('33333333333', 51, '51811111', 'F', 'SERASA'),
('33333333333', 51, '56212222', 'F', 'SERASA'),
('33333333333', 51, '96213333', 'M', 'SERASA')
;
要将行移动到列中,我对记录进行了排序。使用ROW_NUMBER我为每个 cpf 的第一条记录分配了1,为第二条记录分配了1,依此类推。为了避免无休止地重新输入ROW_NUMBER(),我将结果转换为common table expression。 CTE是创建临时,可重用数据集的好方法。最后一步是将编号为1的记录移动到第一组列中,将编号为2的记录移动到第二组中,等等。
将行移动到列中可能需要更详细的解释。我已根据ROW_NUMBER()返回的序列号使用CASE expressions条件移动值。然后我通过cpf GROUPED得到结果。用MAX包装每个case表达式将返回所需的结果。
将行列入列
/* The records from each cdp are numbered.
* The numbering is used to pivot the rows into
* columns.
*/
WITH Sequenced AS
(
-- This CTE numbers the records for each cpf.
SELECT
ROW_NUMBER() OVER (PARTITION BY cpf ORDER BY phone) AS rn,
*
FROM
@Table
)
SELECT
cpf,
-- First set of columns.
MAX(CASE WHEN rn = 1 THEN ddd ELSE NULL END) AS ddd_1,
MAX(CASE WHEN rn = 1 THEN phone ELSE NULL END) AS phone_1,
MAX(CASE WHEN rn = 1 THEN [type] ELSE NULL END) AS type_1,
MAX(CASE WHEN rn = 1 THEN origin ELSE NULL END) AS origin_1,
-- Second set of columns.
MAX(CASE WHEN rn = 2 THEN ddd ELSE NULL END) AS ddd_2,
MAX(CASE WHEN rn = 2 THEN phone ELSE NULL END) AS phone_2,
MAX(CASE WHEN rn = 2 THEN [type] ELSE NULL END) AS type_2,
MAX(CASE WHEN rn = 2 THEN origin ELSE NULL END) AS origin_2,
-- Third set of columns.
MAX(CASE WHEN rn = 3 THEN ddd ELSE NULL END) AS ddd_3,
MAX(CASE WHEN rn = 3 THEN phone ELSE NULL END) AS phone_3,
MAX(CASE WHEN rn = 3 THEN [type] ELSE NULL END) AS type_3,
MAX(CASE WHEN rn = 3 THEN origin ELSE NULL END) AS origin_3,
-- Fourth set of columns
MAX(CASE WHEN rn = 4 THEN ddd ELSE NULL END) AS ddd_4,
MAX(CASE WHEN rn = 4 THEN phone ELSE NULL END) AS phone_4,
MAX(CASE WHEN rn = 4 THEN [type] ELSE NULL END) AS type_4,
MAX(CASE WHEN rn = 4 THEN origin ELSE NULL END) AS origin_4
FROM
Sequenced
GROUP BY
cpf
;
<强>结果
这需要考虑很多。让我们分解一下步骤。首先,CTE添加一个分区行号:
rn cpf ddd phone type origin
1 11111111111 83 81021111 M SERASA
2 11111111111 83 87472222 M SERASA
3 11111111111 83 81023333 M TRANSUNION
4 11111111111 83 88724444 M TRANSUNION
5 11111111111 83 87475555 M TRANSUNION
1 22222222222 43 36271111 F SERASA
2 22222222222 44 36272222 F SERASA
3 22222222222 43 36273333 F TRANSUNION
4 22222222222 43 36284444 F TRANSUNION
1 33333333333 51 51811111 F SERASA
2 33333333333 51 56212222 F SERASA
3 33333333333 51 96213333 M SERASA
接下来,case表达式根据行号将行移动到列中。我只包含一些列和行,以便于阅读。
rn cpf phone_1 phone_2 phone_3
1 11111111111 81021111 NULL NULL
2 11111111111 NULL 87472222 NULL
3 11111111111 NULL NULL 87475555
最后,分组会删除多余的行。 max函数优先于null而不是内容。我再次删除了行和列,以便更容易理解。
rn cpf phone_1 phone_2 phone_3
1 11111111111 81021111 87472222 87475555
2 22222222222 36271111 36272222 36273333
...