在数据透视列中排序而不在结果中

Posted

技术标签:

【中文标题】在数据透视列中排序而不在结果中【英文标题】:Order by in Pivot Column not in Result 【发布时间】:2021-03-14 12:05:07 【问题描述】:

表-A

Productid Brandname
1 C Brand
2 K Brand
3 A Brand

表-B

Productid Rate Slab
1 10 1
2 20 1
3 30 1
1 12 2
2 22 2
3 32 2

动态枢轴查询:-

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(Brandname) from [Table-A] FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)'),1,1,'')
set @query = 'SELECT Slab,' + @cols + '
             from 
             (
                select a.BrandName, b.Rate,b.Slab from [Table-A] a inner join [Table-B] b on a.productid=b.productid 
            ) x
            pivot 
            (
                max(Rate)
                for Brandname in (' + @cols + ')
            ) p '

execute(@query)

结果:-

Slab A Brand C Brand K Brand
1 30 10 20
2 32 12 22

但我需要使用 productid 订购 Brandname 列

预期结果:-

Slab C Brand K Brand A Brand
1 10 20 30
2 12 22 32

【问题讨论】:

【参考方案1】:

在为动态数据透视准备列列表时,使用order by productid并删除 distinct,您的问题将得到解决。

架构和插入语句:

 create table [Table-A](Productid   int,Brandname varchar(10));
 insert into [Table-A] values(1 ,'C Brand');
 insert into [Table-A] values(2 ,'K Brand');
 insert into [Table-A] values(3 ,'A Brand');
 
 create table [Table-B] (Productid  int, Rate   int , Slab int)
 insert into [Table-B] values(1 ,10 ,1);
 insert into [Table-B] values(2 ,20 ,1);
 insert into [Table-B] values(3 ,30 ,1);
 insert into [Table-B] values(1 ,12 ,2);
 insert into [Table-B] values(2 ,22 ,2);
 insert into [Table-B] values(3 ,32,2);

查询:

     DECLARE @cols AS NVARCHAR(MAX),
     @query  AS NVARCHAR(MAX)
 
    select @cols = STUFF((SELECT ',' + QUOTENAME(Brandname) from [Table-A] order by productid FOR XML PATH(''), TYPE
             ).value('.', 'NVARCHAR(MAX)'),1,1,'')
 
    
 set @query = 'SELECT Slab,' + @cols + '
              from 
              (
                 select a.BrandName, b.Rate,b.Slab from [Table-A] a inner join [Table-B] b on a.productid=b.productid 
             ) x
             pivot 
             (
                 max(Rate)
                 for Brandname in (' + @cols + ')
             ) p '
 
 execute(@query)

输出:

Slab C Brand K Brand A Brand
1 10 20 30
2 12 22 32

如果您使用的是 SQL Server 2017 或更高版本,则 string_agg() 将是更智能、更快的选择。

 DECLARE @cols AS NVARCHAR(MAX),
     @query  AS NVARCHAR(MAX)
 
 select distinct @cols=STRING_AGG(quotename(brandname),',')  from [Table-A] 
 
     set @query = 'SELECT Slab,' + @cols + '
                  from 
                  (
                     select a.BrandName, b.Rate,b.Slab from [Table-A] a inner join [Table-B] b on a.productid=b.productid 
                 ) x
                 pivot 
                 (
                     max(Rate)
                     for Brandname in (' + @cols + ')
                 ) p '
     
     execute(@query)

输出:

Slab C Brand K Brand A Brand
1 10 20 30
2 12 22 32

db小提琴here

【讨论】:

@Sathesh Kumar 如果您在此查询中遇到更多困难,请告诉我。 如果对您有帮助,请点击绿色检查以接受此答案。【参考方案2】:

您希望列按特定顺序排列。根据您的数据,您似乎不需要子查询中的SELECT DISTINCT。但如果你这样做,你可以使用聚合来代替:

select @cols = STUFF((SELECT ',' + QUOTENAME(Brandname) 
                      FROM [Table-A]
                      GROUP BY BrandName
                      ORDER BY MIN(ProductId)
                      FOR XML PATH(''), TYPE
                     ).value('.', 'NVARCHAR(MAX)'
                            ), 1, 1, '')

但是,没有聚合:

select @cols = STUFF((SELECT ',' + QUOTENAME(Brandname) 
                      FROM [Table-A]
                      ORDER BY ProductId
                      FOR XML PATH(''), TYPE
                     ).value('.', 'NVARCHAR(MAX)'
                            ), 1, 1, '');

一旦@cols 的顺序正确,查询的其余部分应该就位。

【讨论】:

以上是关于在数据透视列中排序而不在结果中的主要内容,如果未能解决你的问题,请参考以下文章

分类汇总和数据透视表的优缺点

Excle数据透视如何创建多条件汇总的数据透视表

VBA代码在数据透视表旁边的列中向下拖动公式

在新列中显示行数据(透视?)

数据透视表列表中的过时项目

熊猫:从数据透视表中的另一列中减去一列