转置和扩展列数据集T-SQL

时间:2018-12-25 01:22:45

标签: sql sql-server database tsql transpose

我有一个SQL表,看起来像下面的示例在excel中: sample dataset


以下是我想要的结果。我需要将上面的数据转换为2列列表:

Desired result


仅在需要更多信息的情况下,这还是第一张图片,并带有说明我为什么使用现有行的注释: input table + notes

3 个答案:

答案 0 :(得分:2)

UnPivot当然可以提高性能,但是如果您想在不实际使用Dynamic SQL的情况下动态取消数据透视,请考虑以下内容

示例

Select A.fruiteater
      ,C.*
 From  fruits A
 Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
 Cross Apply (
                Select Item  = a.value('local-name(.)','varchar(100)')
                      ,Value = a.value('.','varchar(max)') 
                 From  B.XMLData.nodes('/row')  as C1(n)
                 Cross Apply C1.n.nodes('./@*') as C2(a)
                 Where a.value('local-name(.)','varchar(100)') not in ('fruiteater','OtherColumnsToExclude')
             ) C

返回

fruiteater  Item    Value
Aaron       Fruit1  Orange
Aaron       Fruit2  Pear
Aaron       Fruit3  Apple
Bob         Fruit1  Apple
Bob         Fruit2  Orange
Bob         Fruit3  Blueberries
Bob         Fruit4  Peach
Bob         Fruit5  Mango
Bob         Fruit6  Banana
Carter      Fruit1  Pear
Carter      Fruit2  Orange
Carter      Fruit3  Apple
David       Fruit1  Blueberries
Earnest     Fruit1  Mango
Earnest     Fruit2  Orange
Earnest     Fruit3  Pear
Earnest     Fruit4  Apple
Earnest     Fruit5  Blueberries
Frank       Fruit1  Raspberries

答案 1 :(得分:1)

您可能想使用Unpivot获得预期的结果。

create table fruits (fruiteater varchar(100), Fruit1 varchar(100), Fruit2 varchar(100), 
Fruit3 varchar(100), Fruit4 varchar(100), Fruit5 varchar(100), Fruit6 varchar(100))  

insert into fruits values ('Aaron', 'Orange', 'Pear', 'Apple', NULL, NULL, NULL) 
,('Bob', 'Apple', 'Orange', 'Blueberries', 'Peach', 'Mango', 'Banana') 
,('Carter', 'Pear', 'Orange', 'Apple', NULL, NULL, NULL) 
,('David', 'Blueberries', NULL, NULL, NULL, NULL, NULL) 
,('Earnest', 'Mango', 'Orange', 'Pear', 'Apple','Blueberries', NULL) 
,('Frank', 'Raspberries', NULL, NULL, NULL, NULL, NULL) 

由于所有这些结果都将放在一列中,因此在进行数据透视时要注意数据类型和长度非常重要,因此我确保所有列都属于同一数据类型。

select fruiteater, Value as Fruit from fruits
unpivot 
(value for columnname in ([Fruit1], [Fruit2], [Fruit3], [Fruit4], [Fruit5],[Fruit6]))unpvt 

输出:Unpivot将处理空值,因为它消除了这一点。

fruiteater  Fruit
Aaron   Orange
Aaron   Pear
Aaron   Apple
Bob     Apple
Bob     Orange
Bob     Blueberries
Bob     Peach
Bob     Mango
Bob     Banana
Carter  Pear
Carter  Orange
Carter  Apple
David   Blueberries
Earnest Mango
Earnest Orange
Earnest Pear
Earnest Apple
Earnest Blueberries
Frank   Raspberries

答案 2 :(得分:1)

为此,我更喜欢使用横向连接(apply)。我认为语法更简单,除非您明确希望它能够执行以下操作,否则它不会做任何“魔术”操作,例如删除NULL值:

select f.fruiteater, v.fruit
from fruits f cross apply
     (values (fruit1),  (fruit2),  (fruit3), (fruit4), (fruit5), (fruit6)
     ) v(fruit)
where v.fruit is not null;

更重要的是,unpivot是出于一种目的的非常特定的语法。横向连接非常灵活和强大。用它们来进行透视是了解它们的一种非常简单的方法。