SQL Server 2014では、次のxmlフラグメントがあります。
<salesorder>
<ordnum>123</ordnum>
<orddate>2017-04-17</orddate>
<details>
<detail>
<itemtype>Stationery</itemtype>
<itemdesc>Pencil</itemdesc>
<specifications>
<specification>
<name>Qty</name>
<value>5</value>
</specification>
<specification>
<name>Description</name>
<value>Pencil H1</value>
</specification>
<specification>
<name>Price</name>
<value>1.50</value>
</specification>
</specifications>
</detail>
<detail>
<itemtype>Stationery</itemtype>
<itemdesc>Pencil</itemdesc>
<specifications>
<specification>
<name>Qty</name>
<value>10</value>
</specification>
<specification>
<name>Description</name>
<value>Pencil H2</value>
</specification>
<specification>
<name>Colour</name>
<value>Red</value>
</specification>
<specification>
<name>Price</name>
<value>2.75</value>
</specification>
</specifications>
</detail>
</details>
</salesorder>
次のデータを抽出したいと思います。
ordnum itemtype qty price
123 Stationery 5 1.50
123 Stationery 10 2.75
これはT-SQLで実現できますか?
事前にありがとう、MP
変数_@X
_にXMLを入れます。
_select @X.value('(salesorder/ordnum/text())[1]', 'int') as ordnum,
T.X.value('(itemtype/text())[1]', 'varchar(15)') as itemtype,
T.X.value('(specifications/specification[name/text() = "Qty"]/value/text())[1]', 'int') as qty,
T.X.value('(specifications/specification[name/text() = "Price"]/value/text())[1]', 'money') as price
from @X.nodes('/salesorder/details/detail') as T(X);
_
このクエリの最も複雑な部分は、おそらくQty
とPrice
の値を取得するために使用されるXQuery式です。
[name/text() = "Qty"]
は、ノードname
の値を調べ、Qty
の場合はtrueを返す述語です。
残りは nodes() を使用してXMLを_/salesorder/details/detail
_で細断して詳細要素ごとに1行を取得し、 value() を使用して値を抽出する基本的なXMLクエリです。あなたはあなたのXMLから欲しいです。
以下のt-sqlコードは確かにあなたを助けます。
DECLARE @vXML XML;
SET @vXML = '<salesorder>
<ordnum>123</ordnum>
<orddate>2017-04-17</orddate>
<details>
<detail>
<itemtype>Stationery</itemtype>
<itemdesc>Pencil</itemdesc>
<specifications>
<specification>
<name>Qty</name>
<value>5</value>
</specification>
<specification>
<name>Description</name>
<value>Pencil H1</value>
</specification>
<specification>
<name>Price</name>
<value>1.50</value>
</specification>
</specifications>
</detail>
<detail>
<itemtype>Stationery</itemtype>
<itemdesc>Pencil</itemdesc>
<specifications>
<specification>
<name>Qty</name>
<value>10</value>
</specification>
<specification>
<name>Description</name>
<value>Pencil H2</value>
</specification>
<specification>
<name>Colour</name>
<value>Red</value>
</specification>
<specification>
<name>Price</name>
<value>2.75</value>
</specification>
</specifications>
</detail>
</details>
</salesorder>';
SELECT
salesorder.Col.value('ordnum[1]', 'int')
, detail.Col.value('itemtype[1]', 'varchar(255)')
, specification_qty.Qty AS Qty
, specification_price.Price AS Price
FROM @vXML.nodes('//salesorder') AS salesorder(Col)
CROSS APPLY salesorder.Col.nodes('details') AS details(Col)
CROSS APPLY details.Col.nodes('detail') AS detail(Col)
CROSS APPLY detail.Col.nodes('specifications') AS specifications(Col)
CROSS APPLY (SELECT specification.Col.value('value[1]', 'int') AS Qty FROM specifications.Col.nodes('specification') AS specification(Col) WHERE specification.Col.value('name[1]','VARCHAR(255)') = 'Qty') AS specification_qty
CROSS APPLY (SELECT specification.Col.value('value[1]', 'decimal(3,2)') AS Price FROM specifications.Col.nodes('specification') AS specification(Col) WHERE specification.Col.value('name[1]','VARCHAR(255)') = 'Price') AS specification_price
ソリューションに関する簡単な説明:
提供されるXMLはマルチレベルXMLであるため、データをチャンクで処理する必要があります。したがって、必要な結果を得るために、複数のレベルのxmlを複数のテーブルに分離し、それらをクロス適用する必要があります。単一レベルのXMLデータの場合、単一のSELECT * FROM Tbl
メソッドが機能していた可能性があります。
参照リンク:
Sanchitosがスタックオーバーフローで提供する単一レベルのXMLソリューション
スタックオーバーフローでGeorge Tが提供するマルチレベルXMLソリューション
クロスアプライを使用したSQL Serverのさまざまな階層レベルのXMLのクエリ
これがお役に立てば幸いです。