I have a table called XMLData
that stores an XML file in the Data
column. The structure of the XML is as follows:
<?xml version="1.0" encoding="utf-16"?>
<table>
<id>{c566d133-8512-44c3-b6bd-ea0a9fe473d4}</id>
<rows>
<row>
<columns>
<column name="Item" value="ITEM01" type="System.String" />
<column name="Description" value="Description of item 01" type="System.String" />
<column name="Key" value="1" type="System.Int32" />
</columns>
</row>
<row>
<columns>
<column name="Item" value="ITEM02" type="System.String" />
<column name="Description" value="Description of item 02" type="System.String" />
<column name="Key" value="2" type="System.Int32" />
</columns>
</row>
</rows>
<key>Key</key>
<total>0</total>
<AddOnKey>0</AddOnKey>
<data />
<parameters />
</table>
What I want is to query the XML and get a result like:
Item | Description | Key
------------------------------------------
ITEM01 | Description of item 01 | 1
ITEM02 | Description of item 02 | 2
What I've tried is:
SELECT
Tbl.Col.value('@name', 'nvarchar(128)'),
Tbl.Col.value('@value', 'nvarchar(255)')
FROM
(SELECT CAST(Data AS XML) AS d
FROM XMLData) AS d
CROSS APPLY
d.nodes('//row/columns/column') Tbl(Col)
But that doesn't return the desired result, because it return everything in two columns (name, value). I've thought about going in this direction:
SELECT
Tbl.Col.query('./columns')
FROM
(SELECT CAST(Data As XML) AS d FROM XMLData) AS d
CROSS APPLY
d.nodes('//row') Tbl(Col)
This returns two rows with XML columns:
(No column name)
<columns><column name="Item" value="ITEM01" type="System.String" /><column name="Description" value="Description of item 01" type="System.String" /><column name="Key" value="1" type="System.Int32" /></columns>
<columns><column name="Item" value="ITEM02" type="System.String" /><column name="Description" value="Description of item 02" type="System.String" /><column name="Key" value="2" type="System.Int32" /></columns>
But than I don't know how I can get the separate columns.
You can try to use some calculation for row number, then use condition aggregate function by the row number.
SELECT
MAX(CASE WHEN name = 'Item' then value end) 'Item',
MAX(CASE WHEN name = 'Description' then value end) 'Description',
MAX(CASE WHEN name = 'Key' then value end) 'Key'
FROM (
SELECT
Tbl.Col.value('@name', 'nvarchar(128)') name,
Tbl.Col.value('@value', 'nvarchar(255)') value,
((ROW_NUMBER() OVER(ORDER BY Col)-1) / 3)rn
FROM (SELECT CAST(Data As XML) AS d FROM XMLData) AS d
CROSS APPLY d.nodes('//row/columns/column') Tbl(Col)
) t1
GROUP BY rn
Result
Item Description Key
ITEM01 Description of item 01 1
ITEM02 Description of item 02 2
You can try the below one. Replace @xml.nodes to tablename.columnname.nodes
SELECT DISTINCT
i.y.value('@value', 'varchar(max)') AS Item,
d.y.value('@value', 'varchar(max)') as "Description",
k.y.value('@value', 'varchar(max)') as "Key"
FROM @xml.nodes('//columns//column[@name = "Item"]') AS i(y)
cross apply @xml.nodes('//columns//column[@name = "Description"]') AS d(y)
cross apply @xml.nodes('//columns//column[@name = "Key"]') AS k(y)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.