我有一个包含
等数据的表格 pr comm comm1 comm2 comm comm1 comm2
1 1 1 2 2 2
123 10 0 1 0 0 0
234 20 5 10 0 0 0
345 40 16 21 0 0 0
098 0 0 0 23 65 76
765 0 0 0 45 32 0
981 65 87 9 45 32 100
我希望结果为
inv
我的意思是我必须为每个{{1}}列值生成新列。
答案 0 :(得分:1)
如果你不介意去动态。这种方法需要辅助函数将数据转换为EAV结构(实体属性值)。
Declare @YourTable table (PR int,Inv int,Comm int,Comm1 int,Comm2 int)
Insert Into @YourTable values
(123,1,10, 0, 1),
(234,1,20, 5, 10),
(345,1,40,16, 21),
(098,2,23,65, 76),
(765,2,45,32, 0),
(981,1,65,87, 9),
(981,2,45,32,100)
Select PR=Entity
,Inv
,Col = Concat(B.Attribute,'_',Inv)
,B.Value
Into #Temp
From @YourTable A
Cross Apply (Select * from [dbo].[udf-EAV]((Select A.* for XML RAW)) Where Attribute<>'Inv' ) B
Declare @SQL varchar(max) = ''
Select @SQL = @SQL+','+QUOTENAME(Col)+'=max(IIF(Col='''+col+''',Value,0))' From (Select Top 100 Percent Inv,Col from #Temp Group By Inv,Col Order by Inv) A
Exec('Select PR'+@SQL+' From #Temp Group By PR Order By Pr')
<强>返回强>
UDF
CREATE FUNCTION [dbo].[udf-EAV](@XML xml)
Returns Table
As
Return (
with cteKey(k) as (Select Top 1 xAtt.value('local-name(.)','varchar(100)') From @XML.nodes('/row') As A(xRow) Cross Apply A.xRow.nodes('./@*') As B(xAtt))
Select Entity = xRow.value('@*[1]','varchar(50)')
,Attribute = xAtt.value('local-name(.)','varchar(100)')
,Value = xAtt.value('.','varchar(max)')
From @XML.nodes('/row') As A(xRow)
Cross Apply A.xRow.nodes('./@*') As B(xAtt)
Where xAtt.value('local-name(.)','varchar(100)') Not In (Select k From cteKey)
)
/*
-- Notes: First Field in Query will be the Entity
答案 1 :(得分:1)
首先是UNPIVOT数据,然后做一个PIVOT,如果有很多inv
更好地使用动态SQL来生成和运行你的查询:
SELECT pr,
COALESCE(inv1_comm,0) as inv1_comm,
COALESCE(inv1_comm1,0) as inv1_comm1,
COALESCE(inv1_comm2,0) as inv1_comm2,
COALESCE(inv2_comm,0) as inv2_comm,
COALESCE(inv2_comm1,0) as inv2_comm1,
COALESCE(inv2_comm2,0) as inv2_comm2
FROM (
SELECT pr,
'inv'+CAST(inv as nvarchar(max))+'_'+comms as inv_comms,
[values]
FROM (
SELECT *
FROM YourTable
) as t
UNPIVOT (
[values] FOR comms IN (comm,comm1,comm2)
) as unpv
) as p
PIVOT (
MAX([values]) FOR inv_comms IN (inv1_comm,inv1_comm1,inv1_comm2,inv2_comm,inv2_comm1,inv2_comm2)
) as pvt
输出:
pr inv1_comm inv1_comm1 inv1_comm2 inv2_comm inv2_comm1 inv2_comm2
98 0 0 0 23 65 76
123 10 0 1 0 0 0
234 20 5 10 0 0 0
345 40 16 21 0 0 0
765 0 0 0 45 32 0
981 65 87 9 45 32 100
说明:
首先是UNPIVOT部分
SELECT pr,
'inv'+CAST(inv as nvarchar(max))+'_'+comms as inv_comms,
[values]
FROM (
SELECT *
FROM YourTable
) as t
UNPIVOT (
[values] FOR comms IN (comm,comm1,comm2)
) as unpv
生成此:
pr inv_comms values
123 inv1_comm 10
123 inv1_comm1 0
123 inv1_comm2 1
234 inv1_comm 20
234 inv1_comm1 5
234 inv1_comm2 10
345 inv1_comm 40
345 inv1_comm1 16
345 inv1_comm2 21
etc...
因此,我们从3(N)列的一列中获取所有comms
。
然后我们按照inv
的结果集进行PIVOT扩展。
COALESCE才能生成NULL
个值 - 0
按顺序计算参数,并返回最初未计算为NULL的第一个表达式的当前值。