【问题标题】:MS-SQL Pivot by two columnsMS-SQL 以两列为轴
【发布时间】:2018-09-28 09:29:19
【问题描述】:

我在 MS-SQL 数据库中得到以下数据

Manufacturer|Model|Location|Inventory|Sold
------------|-----|--------|---------|-----
Alpha       |One  |USA     |3000     |123
Alpha       |One  |UK      |2300     |53
Beta        |Two  |USA     |1300     |45
Beta        |Two  |UK      |620      |12
Gamma       |Three|USA     |520      |155
Gamma       |Three|UK      |250      |19

我想获得

Manufacturer|Model|Inventory UK|Sold UK|Inventory USA|Sold USA
------------|-----|------------|-------|-------------|--------
Alpha       |One  |2300        |53     |3000         |123
Beta        |Two  |620         |12     |1300         |45
Gamma       |Three|250         |19     |520          |155

如果我理解正确,我应该旋转两次,但目前我被困在如何获得这个

SELECT *
FROM Data
PIVOT (max([Inventory]) FOR Location IN ([UK],[USA])) Piv1
PIVOT (max([Sold]) FOR Location IN ([UK],[USA])) Piv2
group by Manufacturer,Model,..?

当然,我还远远没有理解我应该如何进行。 有人可以帮帮我吗? 非常感谢

【问题讨论】:

    标签: sql-server pivot


    【解决方案1】:

    这是直接使用 SQL Server 的 PIVOT 运算符执行此操作的一种方法:

    SELECT
        Manufacturer,
        Model,
        MAX(UK) AS [Inventory UK],
        MAX(UK1) AS [Sold UK],
        MAX(USA) AS [Inventory USA],
        MAX(USA1) AS [Sold USA]
    FROM
    (
        SELECT Manufacturer, Model, Location, Location + '1' AS Location1, Inventory, Sold
        FROM Data
    ) AS P
    PIVOT (MAX([Inventory]) FOR Location IN ([UK],[USA])) Piv1
    PIVOT (MAX([Sold]) FOR Location1 IN ([UK1],[USA1])) Piv2
    GROUP BY Manufacturer, Model
    ORDER BY Manufacturer;
    

    Demo

    【讨论】:

    • 我最终也遇到了两个枢轴之间的名称冲突的问题。您介意解释一下“Location1”吗?
    • @Aldo 信不信由你,我通过拼凑查询来凭经验回答。我能做的最多解释就是在不避免名称问题的情况下重复错误消息。为了充分解释,我必须查找PIVOT 的实际实现。
    【解决方案2】:

    您可以使用条件聚合来透视数据:

    declare @tmp table(Manufacturer varchar(50), 
                       Model varchar(50), Location varchar(50), Inventory int, Sold int)
    
    insert into @tmp values
     ('Alpha','One'  ,'USA',3000  ,123)
    ,('Alpha','One'  ,'UK' ,2300  ,53 )
    ,('Beta ','Two'  ,'USA',1300  ,45 )
    ,('Beta ','Two'  ,'UK' ,620   ,12 )
    ,('Gamma','Three','USA',520   ,155)
    ,('Gamma','Three','UK' ,250   ,19 )
    
    select Manufacturer, Model
    ,sum (case when Location ='UK' then Inventory else 0 end) as Inventory_UK
    ,sum (case when Location ='UK' then Sold else 0 end) as Sold_UK
    ,sum (case when Location ='USA' then Inventory else 0 end) as Inventory_USA
    ,sum (case when Location ='USA' then Sold else 0 end) as Sold_USA
    
    from @tmp 
    group by Manufacturer, Model
    order by Manufacturer, Model
    

    结果:

    【讨论】:

    • 效果很好,谢谢!但只是出于好奇......我试图通过两列枢轴来解决它是错误的还是这是唯一的方法?
    • @Aldo 你也可以使用双轴,但我通常使用 group by 因为我有更多的控制权(在我看来)。
    • 感谢安德里亚的澄清!
    【解决方案3】:

    您可以通过执行动态 sql 查询来做到这一点。

    查询

    declare @sql as varchar(max);
    
    select @sql = 'select [Manufacturer], [Model], ' + stuff((
            select distinct ',sum(case [Location] when ' + char(39) + [Location] + char(39) 
            + ' then [Inventory] end) as [Inventory_' + [Location] + ']'
            + ',sum(case [Location] when ' + char(39) + [Location] + char(39) 
            + ' then [Sold] end) as [Sold_' + [Location] + ']'
            from [your_table_name]
            for xml path('')
        )
        , 1, 1, ''
    );
    
    select @sql += 'from [your_table_name] group by [Manufacturer], [Model];';
    
    exec(@sql);
    

    Find a demo here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-28
      • 2020-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多