如何将行转移到具有已知最大列数的列

时间:2011-12-14 17:04:26

标签: sql sql-server-2008

我有一个如下结构的表:

Pricing_Group

GroupID     |   QTY
TestGroup1  |   1
TestGroup1  |   2
TestGroup1  |   4
TestGroup1  |   8
TestGroup1  |   22
TestGroup2  |   2
TestGroup3  |   2
TestGroup3  |   5

我正在寻找的是这样的结果:

Pricing_Group

GroupID     |   QTY1    |   QTY2    |   QTY3    |   QTY4    |   QTY5
TestGroup1  |   1       |   2       |   4       |   8       |   22
TestGroup2  |   2       |   NULL    |   NULL    |   NULL    |   NULL
TestGroup3  |   2       |   5       |   NULL    |   NULL    |   NULL

请注意,对于给定的GroupID,最多只能有 5 不同的数量,而且不知道这5个数量是多少。

这看起来像是PIVOT的一个应用程序,但我无法完全理解像这样的应用程序所需的语法。

感谢您花时间研究这个问题!

3 个答案:

答案 0 :(得分:4)

枢轴的完美案例,您不需要CTE:

Declare @T Table (GroupID varchar(10) not null,
    QTY int)

Insert Into @T
Values ('TestGroup1', 1),
    ('TestGroup1', 2),
    ('TestGroup1', 4),
    ('TestGroup1', 8),
    ('TestGroup1', 22),
    ('TestGroup2', 2),
    ('TestGroup3', 2),
    ('TestGroup3', 5)

Select GroupID, [QTY1], [QTY2], [QTY3], [QTY4], [QTY5]
From (Select GroupID, QTY, 
    RowID = 'QTY' + Cast(ROW_NUMBER() Over (Partition By GroupID Order By QTY) as varchar)
    from @T) As Pvt
Pivot (Min(QTY)
    For RowID In ([QTY1], [QTY2], [QTY3], [QTY4], [QTY5])
    ) As Pvt2

答案 1 :(得分:3)

您可以按生成的排名进行转化;

;with T as (
    select
        rank() over (partition by GroupID order by GroupID, QTY) as rank,
        GroupID, 
        QTY
    from
        THE_TABLE
)
select 
    * 
from 
    T
pivot (
    max(QTY) 
    for rank IN ([1],[2],[3],[4],[5])
) pvt

>> 
GroupID     1     2     3     4     5
----------------------------------------
TestGroup1  1     2     4     8     22
TestGroup2  2     NULL  NULL  NULL  NULL
TestGroup3  2     5     NULL  NULL  NULL

答案 2 :(得分:1)

您还可以使用case语句来执行数据透视:

declare @t table ( GroupID varchar(25), QTY int)
insert into @t
    values  ('TestGroup1', 1),
            ('TestGroup1', 2),
            ('TestGroup1', 4),
            ('TestGroup1', 8),
            ('TestGroup1', 22),
            ('TestGroup2', 2),
            ('TestGroup3', 2),
            ('TestGroup3', 5)

;with cte_Stage (r, GroupId, QTY)
as  (   select  row_number() over(partition by GroupId order by QTY ),
                GroupId,
                QTY
        from    @t
    )
select  GroupId,
        [QTY1] = sum(case when r = 1 then QTY else null end),
        [QTY2] = sum(case when r = 2 then QTY else null end),
        [QTY3] = sum(case when r = 3 then QTY else null end),
        [QTY4] = sum(case when r = 4 then QTY else null end),
        [QTY5] = sum(case when r = 5 then QTY else null end),
        [QTYX] = sum(case when r > 5 then QTY else null end)
from    cte_Stage
group
by      GroupId;