【发布时间】:2018-12-25 01:22:44
【问题描述】:
【问题讨论】:
标签: sql sql-server database tsql transpose
【问题讨论】:
标签: sql sql-server database tsql transpose
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
【讨论】:
Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)。你能解释一下这条线发生了什么吗?具体回复:values、for、XML RAW 和 Foo(XMLData)
unpivot,列定义明确,因为表定义明确。 XML 的强大之处在于pivot。
您可能希望使用 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
【讨论】:
为此,我更喜欢横向连接 (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 是一种非常具体的语法。横向连接非常灵活和强大。使用它们进行反透视是了解它们的一种非常简单的方法。
【讨论】: