简体   繁体   English

取消透视以改变列数

[英]Unpivot with varying number of columns

I have been given a table of data that I need to extract and normalize. 我已经得到一张需要提取和规范化的数据表。 It looks like this: 看起来像这样:

AccountName BrandCoke BrandPepsi BrandDiet SalesCoke SalesPepsi SalesDiet
Account1       X          X                  100       200                
Account2                  X          X                 300        400
Account3       X                             500

I need to normalize it, converting columns to rows like so: 我需要对其进行标准化,将列转换为行,如下所示:

AccountName  Brand  Sales
Account1     Coke   100
Account1     Pepsi  200
Account2     Pepsi  300
Account2     Diet   400
Account3     Coke   500

It looks like a good candidate for using UNPIVOT , except I am unsure how to account for the fact that the brand name depends on whether there is an "X" in columns 2-4 and the fact that I only need a row for the brand if there is an "X" in that brand's column. 看起来很适合使用UNPIVOT ,不过我不确定如何解释品牌名称取决于2-4列中是否有“ X”的事实以及该品牌我只需要一行的事实该品牌的列中是否有“ X”。 (So only 5 rows should be generated, not 9) (因此,仅应生成5行,而不是9行)

My other thought was to use the SQL2000 way of doing this before UNPIVOT and do separate SELECTS like this: 我的另一个想法是在UNPIVOT之前使用SQL2000的方式进行此操作,并像这样进行单独的SELECTS

SELECT AccountName, Brand='Coke', Sales = SalesCoke FROM T WHERE BrandCoke = 'X'
UNION
SELECT AccountName, Brand='Pepsi', Sales = SalesPepsi FROM T WHERE BrandPepsi = 'X'
UNION
SELECT AccountName, Brand='Diet', Sales = SalesDiet FROM T WHERE BrandDiet = 'X'

But that seems rather inelegant. 但这似乎不太优雅。

Can this be done easily with UNPIVOT, or is UNIONing multiple SELECTs a better solution? 可以使用UNPIVOT轻松完成此操作,还是UNIONing多个SELECT是更好的解决方案?

Since you are using SQL Server 2008 you should be able to use CROSS APPLY with VALUES to unpivot the columns in pairs. 由于您使用的是SQL Server 2008,因此您应该可以将CROSS APPLY与VALUES一起使用,以取消对成对的列的操作。 The syntax will be: 语法为:

select AccountName, Brand, Sales
from yourtable
cross apply
(
  values
    ('Coke', BrandCoke, SalesCoke),
    ('Pepsi', BrandPepsi, SalesPepsi),
    ('Diet', BrandDiet, SalesDiet)
) c (Brand, origCol, Sales)
where origCol is not null;

See SQL Fiddle with Demo 参见带有演示的SQL Fiddle

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM