SQL如何将数据转置并分组到静态列?

时间:2018-05-07 16:01:30

标签: sql sql-server

我有一张包含以下数据的表格:

UID  LAST    FIRST  FUND  AMOUNT  STATUS
1    Smith   John   C     100     1
1    Smith   John   B     250     1
1    Smith   John   E     150     1
2    Jones   Meg    B     275     1
2    Jones   Meg    F     150     1
3    Carter  Bill   A     100     1

我想将每个UID的FUND,AMOUNT和STATUS值转换为每个UID的单行。生成的表格将为FUND_1,AMT_1,STATUS_1,FUND_2,AMT_2,STATUS_2,FUND_3,AMT_3,STATUS_3添加列。每个UID可能有也可能没有总共3个基金。如果他们不这样做,剩余的资金,amt和状态列将留空。结果表将显示为:

UID  LAST   FIRST  FUND_1  AMT_1  STATUS_1  FUND_2  AMT_2  STATUS_2  FUND_3  AMT_3  STATUS_3
1    Smith  John   C       100    1         B       250    1         E       150    1
2    Jones  Meg    B       275    1         F       150    1
3    Carter Bill   A       100    1

为了澄清,这是数据如何从现有表移动到UID 1的结果表:

How data moves

似乎我无法使用PIVOT,因为FUND_1,FUND_2,FUND_3将是每个人不同的基金类别。问题TSQL Pivot without aggregate function有帮助,但没有回答我的问题,因为我在该问题中的DBColumnName中有多行。

1 个答案:

答案 0 :(得分:2)

这是一种非常常见的条件聚合。请注意我如何将耗材数据作为表和插入语句发布。说实话,这部分比实际代码选择数据需要更长的时间。你将来应该这样做。您还应该避免使用关键字作为列名。

declare @Something table
(
    UID int
    , LAST varchar(10)
    , FIRST varchar(10)
    , FUND char(1)
    , AMOUNT int
    , STATUS int
)

insert @Something values
(1, 'Smith', 'John', 'C', 100, 1)
, (1, 'Smith', 'John', 'B', 250, 1)
, (1, 'Smith', 'John', 'E', 150, 1)
, (2, 'Jones', 'Meg', 'B', 275, 1)
, (2, 'Jones', 'Meg', 'F', 150, 1)
, (3, 'Carter', 'Bill', 'A', 100, 1)
;

with SortedValues as
(
    select *
        , RowNum = ROW_NUMBER() over(partition by UID order by (select null))
    from @Something
)

select UID
    , Last
    , First
    , Fund_1 = max(case when RowNum = 1 then Fund end)
    , Amt_1 = max(case when RowNum = 1 then Amount end)
    , Status_1 = max(case when RowNum = 1 then Status end)

    , Fund_2 = max(case when RowNum = 2 then Fund end)
    , Amt_2 = max(case when RowNum = 2 then Amount end)
    , Status_2 = max(case when RowNum = 2 then Status end)

    , Fund_3 = max(case when RowNum = 3 then Fund end)
    , Amt_3 = max(case when RowNum = 3 then Amount end)
    , Status_3 = max(case when RowNum = 3 then Status end)
from SortedValues
group by UID
    , Last
    , First
order by UID
    , Last
    , First