想象一下带有属性的表(键值)和带有Lots的父表。
LotId SomeText
----------- --------
1 Hello
2 World
AttributeId LotId Val Kind
----------- ----------- -------- --------
1 1 Foo1 Kind1
2 1 Foo2 Kind2
3 2 Bar1 Kind1
4 2 Bar2 Kind2
5 2 Bar3 Kind3
我正在使用UNPIVOT
- PIVOT
操作来获取以下形式的数据:
LotId SomeText AttributeId LotId Kind1Val Kind AttributeId LotId Kind2Val Kind AttributeId LotId Kind3Val Kind
----------- -------- ----------- ----------- -------- -------- ----------- ----------- -------- -------- ----------- ----------- -------- --------
1 Hello 1 1 Foo1 Kind1 2 1 Foo2 Kind2 NULL NULL NULL NULL
2 World 3 2 Bar1 Kind1 4 2 Bar2 Kind2 5 2 Bar3 Kind3
如何选择远离属性表值的数据独立性。
错误结果的示例:
LotId SomeText attributeid_1 LotId_1 Value_1 Kind_1 attributeid_2 LotId_2 Value_2 Kind_2 attributeid_3 LotId_3 Value_3 Kind_3
----------- -------- ------------- -------- -------- -------- ------------- -------- -------- -------- ------------- -------- -------- --------
1 Hello 4 1 Foo1 Kind1 NULL NULL NULL NULL NULL NULL NULL NULL
2 World 1 2 Bar2 Kind2 3 2 Bar3 Kind3 2 2 Bar1 Kind8
为什么?
由于Kind2
列中的Kind_1
文字和Kind3
中的Kind_2
。
DECLARE @Lot TABLE ( LotId INT PRIMARY KEY IDENTITY, SomeText VARCHAR(8)) INSERT INTO @Lot VALUES ('Hello'), ('World') DECLARE @Attribute TABLE( AttributeId INT PRIMARY KEY IDENTITY, LotId INT, Val VARCHAR(8), Kind VARCHAR(8)) INSERT INTO @Attribute VALUES (2, 'Bar2', 'Kind2'), (2, 'Bar1', 'Kind8'), (2, 'Bar3', 'Kind3'), (1, 'Foo1', 'Kind1') select * from ( select LotId, SomeText, col+'_'+CAST(rn as varchar(10)) col, value from ( select l.LotId, l.SomeText, cast(a.AttributeId as varchar(8)) attributeid, cast(a.LotId as varchar(8)) a_LotId, a.Val, a.Kind, ROW_NUMBER() over(partition by l.lotid order by a.kind) rn from @Lot l left join @Attribute a on l.LotId = a.LotId ) src cross apply ( values ('attributeid', attributeid),('LotId', a_LotId), ('Value', Val), ('Kind', Kind) ) c (col, value) ) d pivot ( max(value) for col in (attributeid_1, LotId_1, Value_1, Kind_1, attributeid_2, LotId_2, Value_2, Kind_2, attributeid_3, LotId_3, Value_3, Kind_3) ) piv
正确结果的示例:
LotId SomeText attributeid_Kind1 LotId_Kind1 Value_Kind1 Kind_Kind1 attributeid_Kind2 LotId_Kind2 Value_Kind2 Kind_Kind2 attributeid_Kind3 LotId_Kind3 Value_Kind3 Kind_Kind3
----------- -------- ----------------- ----------- ----------- ---------- ----------------- ----------- ----------- ---------- ----------------- ----------- ----------- ----------
1 WithAll 1 1 Foo1 Kind1 2 1 Foo2 Kind2 3 1 Foo3 Kind3
2 Hello NULL NULL NULL NULL 10 2 Bar2 Kind2 NULL NULL NULL NULL
3 World NULL NULL NULL NULL NULL NULL NULL NULL 12 3 Bar3 Kind3
由于KindX
位于Kind_x
列等,
DECLARE @Lot TABLE ( LotId INT PRIMARY KEY IDENTITY, SomeText VARCHAR(8)) INSERT INTO @Lot VALUES ('WithAll'), ('Hello'), ('World') DECLARE @Attribute TABLE( AttributeId INT PRIMARY KEY IDENTITY, LotId INT, Val VARCHAR(8), Kind VARCHAR(8)) INSERT INTO @Attribute VALUES (1, 'Foo1', 'Kind1'), (1, 'Foo2', 'Kind2'), (1, 'Foo3', 'Kind3'), (1, 'Foo4', 'Kind4'), (1, 'Foo5', 'Kind5'), (1, 'Foo6', 'Kind6'), (1, 'Foo7', 'Kind7'), (1, 'Foo8', 'Kind8'), (1, 'Foo9', 'Kind9'), (2, 'Bar2', 'Kind2'), (2, 'Bar1', 'Kind8'), (3, 'Bar3', 'Kind3') DECLARE @AttributesMask TABLE( Kind VARCHAR(8) ) INSERT INTO @AttributesMask VALUES('Kind1'), ('Kind2'), ('Kind3'), ('Kind4'), ('Kind5'), ('Kind6'), ('Kind7'), ('Kind8') select * from( select LotId, SomeText, --col+'_'+CAST(rn as varchar(10)) col, col+'_'+[Kind] col, value from ( select l.LotId, l.SomeText, cast(a.AttributeId as varchar(8)) attributeid, cast(a.LotId as varchar(8)) a_LotId, a.Val, a.Kind --, ROW_NUMBER() over(partition by l.[LotId] order by am.[Kind]) rn FROM @AttributesMask AS am LEFT join @Attribute a on [am].[Kind] = [a].[Kind] LEFT JOIN @Lot l ON [a].[LotId] = [l].[LotId] ) src cross apply ( values ('attributeid', attributeid),('LotId', a_LotId), ('Value', Val), ('Kind', Kind) ) c (col, value) ) d PIVOT (max(value) for col in ( attributeid_Kind1, LotId_Kind1, Value_Kind1, Kind_Kind1, attributeid_Kind2, LotId_Kind2, Value_Kind2, Kind_Kind2, attributeid_Kind3, LotId_Kind3, Value_Kind3, Kind_Kind3)) piv ORDER BY LotId
为了得到正确的结果,我使用了掩码来预先安排作为PIVOT源的数据。如果没有面具怎么办?
参考问题:How to replace a functional (many) OUTER APPLY (SELECT * FROM)
答案 0 :(得分:0)
除非我在您的解释中遗漏了某些内容,否则您不需要AttributeMask
。如果最终的列名称只是原始列名称,然后是Kind
值,那么您可以使用:
select *
from
(
select LotId,
SomeText,
col+'_'+Kind col,
value
from
(
select l.LotId,
l.SomeText,
cast(a.AttributeId as varchar(8)) attributeid,
cast(a.LotId as varchar(8)) a_LotId,
a.Val,
a.Kind
from @Lot l
left join @Attribute a
on l.LotId = a.LotId
) src
cross apply
(
values ('attributeid', attributeid),('LotId', a_LotId), ('Value', Val), ('Kind', Kind)
) c (col, value)
) d
pivot
(
max(value)
for col in (attributeid_Kind1, LotId_Kind1, Value_Kind1, Kind_Kind1,
attributeid_Kind2, LotId_Kind2, Value_Kind2, Kind_Kind2,
attributeid_Kind3, LotId_Kind3, Value_Kind3, Kind_Kind3)
) piv;
见SQL Fiddle with Demo。这给出了结果:
| LOTID | SOMETEXT | ATTRIBUTEID_KIND1 | LOTID_KIND1 | VALUE_KIND1 | KIND_KIND1 | ATTRIBUTEID_KIND2 | LOTID_KIND2 | VALUE_KIND2 | KIND_KIND2 | ATTRIBUTEID_KIND3 | LOTID_KIND3 | VALUE_KIND3 | KIND_KIND3 |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 1 | WithAll | 1 | 1 | Foo1 | Kind1 | 2 | 1 | Foo2 | Kind2 | 3 | 1 | Foo3 | Kind3 |
| 2 | Hello | (null) | (null) | (null) | (null) | 10 | 2 | Bar2 | Kind2 | (null) | (null) | (null) | (null) |
| 3 | World | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | 12 | 3 | Bar3 | Kind3 |