如何在SQL Server 2008中将行切换为列,反之亦然

时间:2016-09-01 05:44:23

标签: sql-server-2008 pivot

我有问题在SQL Server 2008中将行切换到列,反之亦然,我已尝试对解决方案进行任何查询,但我没有得到正确的结果。

我有一张表如下:

declare @tmpTable table 
(name varchar(20), date_ date, sales_code char(1), sales smallint, earned int)

insert into @tmpTable 
values ('Robert', '2016/8/1', 'A', 2, 30),
('Robert', '2016/8/1', 'B', 3, 45),
('Robert', '2016/8/2', 'B', 1, 15),
('Robert', '2016/8/3', 'B', 2, 30),
('Jhon', '2016/8/1', 'A', 3, 45),
('Jhon', '2016/8/2', 'A', 3, 45),
('Jhon', '2016/8/3', 'B', 2, 30)

select * from @tmpTable;

结果:

Name        date_           sales_code  sales   earned
------      ----------      ----------  -----   ------
Robert      2016-08-01      A           2       30
Robert      2016-08-01      B           3       45
Robert      2016-08-02      B           1       15
Robert      2016-08-03      B           2       30
Jhon        2016-08-01      A           3       45
Jhon        2016-08-02      A           3       45
Jhon        2016-08-03      B           2       30

然后,我有下一个查询:

select * from (
select name, 'sales_code' as category, date_, sales_code from (
select * from (
SELECT  name, date_
       ,STUFF((SELECT ', ' + sales_code [text()]
         FROM @tmpTable 
         WHERE date_ = t.date_
         FOR XML PATH(''), TYPE)
        .value('.','NVARCHAR(MAX)'),1,2,' ') sales_code
                ,STUFF((SELECT ', ' + convert(varchar(max), sales) [text()]
         FROM @tmpTable 
         WHERE date_ = t.date_
         FOR XML PATH(''), TYPE)
        .value('.','NVARCHAR(MAX)'),1,2,' ') sales
                ,STUFF((SELECT ', ' + convert(varchar(max), earned) [text()]
         FROM @tmpTable 
         WHERE date_ = t.date_
         FOR XML PATH(''), TYPE)
        .value('.','NVARCHAR(MAX)'),1,2,' ') earned
FROM @tmpTable t
GROUP BY name, date_
) as a
) as a
) as a
pivot (
    max(sales_code) FOR date_ IN ([2016/8/1], [2016/8/2], [2016/8/3])
)as pv

union all

select * from (
select name, 'sales' as category, date_, sales from (
select * from (
SELECT  name, date_
       ,STUFF((SELECT ', ' + sales_code [text()]
         FROM @tmpTable 
         WHERE date_ = t.date_
         FOR XML PATH(''), TYPE)
        .value('.','NVARCHAR(MAX)'),1,2,' ') sales_code
                ,STUFF((SELECT ', ' + convert(varchar(max), sales) [text()]
         FROM @tmpTable 
         WHERE date_ = t.date_
         FOR XML PATH(''), TYPE)
        .value('.','NVARCHAR(MAX)'),1,2,' ') sales
                ,STUFF((SELECT ', ' + convert(varchar(max), earned) [text()]
         FROM @tmpTable 
         WHERE date_ = t.date_
         FOR XML PATH(''), TYPE)
        .value('.','NVARCHAR(MAX)'),1,2,' ') earned
FROM @tmpTable t
GROUP BY name, date_
) as a
) as a
) as a
pivot (
    max(sales) FOR date_ IN ([2016/8/1], [2016/8/2], [2016/8/3])
)as pv

union all

select * from (
select name, 'earned' as category, date_, earned from (
select * from (
SELECT  name, date_
       ,STUFF((SELECT ', ' + sales_code [text()]
         FROM @tmpTable 
         WHERE date_ = t.date_
         FOR XML PATH(''), TYPE)
        .value('.','NVARCHAR(MAX)'),1,2,' ') sales_code
                ,STUFF((SELECT ', ' + convert(varchar(max), sales) [text()]
         FROM @tmpTable 
         WHERE date_ = t.date_
         FOR XML PATH(''), TYPE)
        .value('.','NVARCHAR(MAX)'),1,2,' ') sales
                ,STUFF((SELECT ', ' + convert(varchar(max), earned) [text()]
         FROM @tmpTable 
         WHERE date_ = t.date_
         FOR XML PATH(''), TYPE)
        .value('.','NVARCHAR(MAX)'),1,2,' ') earned
FROM @tmpTable t
GROUP BY name, date_
) as a
) as a
) as a
pivot (
    max(earned) FOR date_ IN ([2016/8/1], [2016/8/2], [2016/8/3])
)as pv

它将显示结果:

name        category    2016/8/1        2016/8/2    2016/8/3
-------     --------    --------        -------     --------
Jhon        sales_code  A, B, A         B, A        B, B
Robert      sales_code  A, B, A         B, A        B, B
Jhon        sales       2, 3, 3         1, 3        2, 2
Robert      sales       2, 3, 3         1, 3        2, 2
Jhon        earned      30, 45, 45      15, 45      30, 30
Robert      earned      30, 45, 45      15, 45      30, 30

但是,我想得到以下结果:

name        category    2016/8/1    2016/8/2    2016/8/3
----        --------    --------    --------    --------
Robert      sales_code  A, B        B           B
Robert      sales       2, 3        1           2
Robert      earned      30, 45      15          30
Jhon        sales_code  A           A           B
Jhon        sales       3           3           2
Jhon        earned      45          45          30

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

首先你需要取消数据的移动..要做到这一点,所有数据类型都匹配很多,所以你需要将2个数字列转换为varchars。

在你想要获取每个名称的组合值,date_之前仍然使用东西,但是使用distinct来获取名称,date_值一次。

取消投影后,您只需再次转动。

SELECT  *
FROM (  SELECT  DISTINCT
                Name, 
                date_,
                sales_code = STUFF((SELECT ', ' + sales_code 
                                    FROM @tmpTable t2 
                                    WHERE t2.Name = t.Name AND t2.date_ = t.date_ 
                                    FOR XML PATH('')), 1, 2, ''),
                sales      = STUFF((SELECT ', ' + CONVERT(VARCHAR, sales) 
                                    FROM @tmpTable t2 
                                    WHERE t2.Name = t.Name AND t2.date_ = t.date_ 
                                    FOR XML PATH('')), 1, 2, ''),
                earned     = STUFF((SELECT ', ' + CONVERT(VARCHAR, earned) 
                                    FROM @tmpTable t2 
                                    WHERE t2.Name = t.Name AND t2.date_ = t.date_ 
                                    FOR XML PATH('')), 1, 2, '') 
        FROM    @tmpTable t) t
UNPIVOT (
    val 
    FOR category IN (sales_code, sales, earned)
) up
PIVOT (
    MAX(val)
    FOR date_ IN ([2016-08-01], [2016-08-02], [2016-08-03])
) p
ORDER BY name DESC, 
        category DESC