【问题标题】:PIVOT to pivot rows into columns dynamicallyPIVOT 动态地将行旋转到列中
【发布时间】:2018-06-28 19:16:55
【问题描述】:

我在每一行都有一张客户表及其购买类型和购买说明。

我想调整购买类型和备注,以便每一行只代表一个客户实例。

表格

Customer ID  | Name | Purchase Type | Purchase Notes
-------------+------+---------------+---------------
1            | John | Furniture     | TextABC 
1            | John | Appliance     | TextDEF 
1            | John | Accessory     | TextGHI 

目标

Customer ID  | Name | Purchase Type 1 | Purchase Notes 1 | Purchase Type 2| Purchase Notes 2  | Purchase Type 3 | Purchase Notes 3
------------ +------+-----------------+------------------+----------------+-------------------+-----------------+------------------
1            | John | Furniture       |TextABC           | Appliance      | TextDEF           | Accessory       | TextGHI

要求

我无法对任何购买类型或备注进行硬编码,因为它们可以更改。 我无法确定有多少种类型,因为它可能是 9 种或 4 种,具体取决于客户。

如何将编号添加到标题中,以便表格最多可以包含 x,但那些小于 x 的客户只会有空白?

阅读有关 SQL Pivot 的论坛,我似乎无法找到一种方法来做到这一点,而无需对其进行硬编码。

【问题讨论】:

    标签: sql sql-server tsql pivot


    【解决方案1】:

    你可以使用动态TSQL和PIVOT:

    if OBJECT_ID('dbo.test') is null 
        create table dbo.test (CustomerID int , [Name] varchar(50), PurchaseType varchar(50), PurchaseNotes varchar(50))
    truncate table dbo.test 
    
    --populate test table
    insert into dbo.test values
     (1, 'John','Furniture','TextABC'), (1, 'John','Appliance','TextDEF'), (1, 'John','Accessory','TextGHI')
    ,(2, 'Mary','Furniture','TextJKL'), (2, 'Mary','Appliance','TextMNO'), (2, 'Mary','Accessory','TextPQR'), (2, 'Mary','New type','TextSTU') 
    
    declare @total         int
    declare @counter       int = 1
    declare @PurchaseNotes nvarchar(max)='' --holds all the PurchaseNotes column names 
    declare @PurchaseType  nvarchar(max)='' --holds all the PurchaseType column names  
    declare @Combo         nvarchar(max)='' --holds the combination of PurchaseType and PurchaseNotes for the final SELECT statement
    declare @sql           nvarchar(max)='' --contains the TSQL dinamically generated 
    
    --count distinct Purchase Types
    select @total = count(distinct [PurchaseType]) from dbo.test 
    
    --build headers
    while @counter <= @total
        begin
           set @PurchaseNotes = @PurchaseNotes + ' [PurchaseNotes' + cast(@counter as varchar(max)) + '],'
           set @PurchaseType = @PurchaseType + ' [PurchaseType' + cast(@counter as varchar(max)) + '],'
           set @Combo = @Combo + ' [PurchaseType' + cast(@counter as varchar(max)) + '],'+ ' [PurchaseNotes' + cast(@counter as varchar(max)) + '],'
           set @counter = @counter + 1
        end
    
    set @PurchaseNotes = left(@PurchaseNotes,len(@PurchaseNotes)-1) + ' '
    set @PurchaseType = left(@PurchaseType,len(@PurchaseType)-1)+ ' '
    set @Combo = left(@Combo,len(@Combo)-1)+ ' '
    
    --create dynamic TSQL query
    set @sql = @sql + ' SELECT T.CustomerID, T.[Name],' + @Combo
    set @sql = @sql + ' FROM '
    set @sql = @sql + ' ( '
    set @sql = @sql + '     SELECT [CustomerID],[Name],[PurchaseType],'
    set @sql = @sql + '         CONCAT(''PurchaseType'',ROW_NUMBER() OVER (PARTITION BY customerid ORDER BY customerid, [Name])) AS COL  '
    set @sql = @sql + '     FROM  dbo.test '
    set @sql = @sql + ' ) SRC '
    set @sql = @sql + ' PIVOT '
    set @sql = @sql + ' ( '
    set @sql = @sql + '     MAX(PurchaseType) '
    set @sql = @sql + '     FOR COL IN (' + @PurchaseType + ') '
    set @sql = @sql + ' ) AS T '
    set @sql = @sql + ' inner join '
    set @sql = @sql + ' ('
    set @sql = @sql + '     SELECT * '
    set @sql = @sql + '     FROM '
    set @sql = @sql + '     ( '
    set @sql = @sql + '         SELECT [CustomerID],[Name],[PurchaseNotes],'
    set @sql = @sql + '             CONCAT(''PurchaseNotes'',ROW_NUMBER() OVER (PARTITION BY customerid ORDER BY customerid, [Name])) AS COL2 '
    set @sql = @sql + '         FROM  dbo.test '
    set @sql = @sql + '     ) SRC '
    set @sql = @sql + '      PIVOT '
    set @sql = @sql + '     ( '
    set @sql = @sql + '         MAX(PurchaseNotes) '
    set @sql = @sql + '         FOR COL2 IN (' + @PurchaseNotes + ') '
    set @sql = @sql + '     ) AS PVT2 '
    set @sql = @sql + ' ) N'
    set @sql = @sql + '  on T.CustomerID = N.CustomerID'
    
    --execute dynamic query
    exec (@sql)
    

    输入(我用新的 PurchaseType 添加了另一个客户):

    结果:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-16
      • 2012-10-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多