使用SQL Server 2014 Standard Edition,是否可以对XML列名的值进行PIVOT?最后,我想接受这个:
<table>
<id>{3d2699c4-3159-4e8b-b48c-c2c4c9b5bd77}</id>
<rows>
<row>
<columns>
<column name="DESC" value="DACS" type="System.String" />
<column name="ec_amount" value="5000" type="System.Decimal" />
<column name="ec_exrate" value="1" type="System.Decimal" />
<column name="ec_total" value="5000.00" type="System.Decimal" />
<column name="ItemNo" value="PVT-C30" type="System.String" />
<column name="UOM" value="EA" type="System.String" />
<column name="DefaultKey" value="1" type="System.Int32" /><----THIS IS THE COLUMN ON WHICH I WOULD LIKE TO PIVOT
</columns>
</row>
<row>
<columns>
<column name="DESC" value="DACS" type="System.String" />
<column name="ec_amount" value="1500" type="System.Decimal" />
<column name="ec_exrate" value="5" type="System.Decimal" />
<column name="ec_total" value="7500.00" type="System.Decimal" />
<column name="ItemNo" value="PVT-C30" type="System.String" />
<column name="UOM" value="EA" type="System.String" />
<column name="DefaultKey" value="2" type="System.Int32" />
</columns>
</row>
</rows>
<key>DefaultKey</key>
<total>12500.00</total>
<data />
<parameters />
</table>
....并创建这些结果:
DefaultKey DESC ec_amount ec_exrate ec_total ItemNo UOM
1 DACS 5000 1 5000 PVT-C30 EA
2 DACS 1500 5 7500 PVT-C30 EA
我已经搜索了Stack Overflow网站以及我遇到的所有内容,这两个帖子很接近,但他们并没有让我在那里:
How do I Pivot on an XML column's attributes in T-SQL
如果已经解决这个问题,我很抱歉,我只是放弃了。
答案 0 :(得分:1)
无需转动......试试这个
DECLARE @xml XML=N'<table>
<id>{3d2699c4-3159-4e8b-b48c-c2c4c9b5bd77}</id>
<rows>
<row>
<columns>
<column name="DESC" value="DACS" type="System.String" />
<column name="ec_amount" value="5000" type="System.Decimal" />
<column name="ec_exrate" value="1" type="System.Decimal" />
<column name="ec_total" value="5000.00" type="System.Decimal" />
<column name="ItemNo" value="PVT-C30" type="System.String" />
<column name="UOM" value="EA" type="System.String" />
<column name="DefaultKey" value="1" type="System.Int32" />
</columns>
</row>
<row>
<columns>
<column name="DESC" value="DACS" type="System.String" />
<column name="ec_amount" value="1500" type="System.Decimal" />
<column name="ec_exrate" value="5" type="System.Decimal" />
<column name="ec_total" value="7500.00" type="System.Decimal" />
<column name="ItemNo" value="PVT-C30" type="System.String" />
<column name="UOM" value="EA" type="System.String" />
<column name="DefaultKey" value="2" type="System.Int32" />
</columns>
</row>
</rows>
<key>DefaultKey</key>
<total>12500.00</total>
<data />
<parameters />
</table>';
SELECT r.value(N'(columns/column[@name="DefaultKey"]/@value)[1]',N'int') AS DefaultKey
,r.value(N'(columns/column[@name="DESC"]/@value)[1]',N'nvarchar(max)') AS [DESC]
,r.value(N'(columns/column[@name="ec_amount"]/@value)[1]',N'decimal(10,4)') AS ec_amount
--similar with your other elements
FROM @xml.nodes(N'/table/rows/row') AS A(r)
答案 1 :(得分:0)
您基本上需要为每个&#34;行&#34;分配行号。 XML(或找出区分每个&#34;行&#34;的其他方法)。你可以解决这个问题的一种方法是从每个&#34;行&#34;中提取默认密钥。 (通过使用窗口函数和分区):
SELECT *
FROM
(
SELECT Name = C2.X.value('@name', 'varchar(max)'),
Val = C2.X.value('@value', 'varchar(max)'),
DefaultKey = MAX(CASE WHEN C2.X.value('@name', 'varchar(max)') = 'DefaultKey' THEN C2.X.value('@value', 'varchar(max)') END) OVER(PARTITION BY C1.X)
FROM myTable
CROSS APPLY myXMLColumn.nodes('table/rows/row/columns') AS C1(X)
CROSS APPLY C1.X.nodes('column') AS C2(X)
) AS T
PIVOT (MAX(Val) FOR Name IN ([DESC], [ec_amount], [ec_exrate], [ec_total], [ItemNo], [UOM])) AS P;
如果DefaultKey不是唯一的,您可以使用行号或排名窗口函数代替每个类似的结果:
SELECT *
FROM
(
SELECT Name = C2.X.value('@name', 'varchar(max)'),
Val = C2.X.value('@value', 'varchar(max)'),
RowInXML = DENSE_RANK() OVER (ORDER BY C1.X)
FROM myTable
CROSS APPLY myXMLColumn.nodes('table/rows/row/columns') AS C1(X)
CROSS APPLY C1.X.nodes('column') AS C2(X)
) AS T
PIVOT (MAX(Val) FOR Name IN ([DefaultKey], [DESC], [ec_amount], [ec_exrate], [ec_total], [ItemNo], [UOM])) AS P;