我有以下xml。如何在不创建重复行的情况下,在遇到新的cond-id之前保留每个cond-id的值并将其应用于每个后续的price-container元素。
我尝试了几件事,这是我最近来的事情。
declare @xml xml =
'-<module mod-id="333">
<title>NNN NNNNN NNNNN</title>
-<data-code>
<code-id>333-004</code-id>
<description>XXX XXX XXXXXXXX XXX X XXXXXXXXXXXXXXXX</description>
-<applic>
-<p32>
-<condition cond-id="o-000008888">
<ctext> NNN NNNNNNNNN NN NNNNN NNNNNNNNN NN</ctext>
</condition>
-<m234 domicile="all" ver-start="4.40" target-ver="4.40" vocation="all">
-<value>
<price-container pwdb-id="p-000121212">267</price-container>
<weight-container pwdb-id="w-000676767">0/40</weight-container>
</value>
</m234>
</p32>
</applic>
</data-code>
-<data-code>
<code-id>333-005</code-id>
<description>NNNNNNNNNNNNN NNNNNNNNNN NNNNN N NNNN N NNN NNNNNNNN</description>
-<applic>
-<p32>
-<condition cond-id="o-000002222">
<ctext> NNNNNN NNNNN XXXX NNNN XXXX NNNNNNNN XXXXXXXX </ctext>
</condition>
-<m234 domicile="all" ver-start="4.40" target-ver="4.40" vocation="all">
-<value>
<price-container pwdb-id="p-000123456">N/C</price-container>
<weight-container pwdb-id="w-000234567">0/0</weight-container>
</value>
</m234>
-<condition cond-id="o-000033333">
<ctext> Price with DC 622-005 , DC 622-197, , and DC 622-292 </ctext>
</condition>
-<m234 domicile="all" ver-start="4.80" target-ver="4.80" vocation="all">
-<value>
<price-container pwdb-id="p-000456789">99999</price-container>
<weight-container pwdb-id="w-000789012">0/0</weight-container>
</value>
</m234>
</p32>
</applic>
</data-code>
</module>'
select
price.value('(../../../../../code-id)[1]', 'varchar(50)') as data_code,
price.value('@pwdb-id', 'varchar(50)') as pwdb_id,
price.value('(text())[1]', 'varchar(50)') as text,
cond.value('(@cond-id) [1]', 'varchar(50)') as cond_id
from @xml.nodes('/module/data-code/applic/p32') as Xtble(datanode)
cross apply Xtble.datanode.nodes('m234/value/price-container') as Xtble2(price)
outer apply Xtble.datanode.nodes('condition') as Xtble3(cond)
这就是我要得到的
data_code pwdb_id text cond_id
333-004 p-000121212 267 o-000008888
333-005 p-000123456 N/C o-000002222
333-005 p-000456789 99999 o-000002222
333-005 p-000123456 N/C o-000033333
333-005 p-000456789 99999 o-000033333
这就是我想要的
data_code pwdb_id text cond_id
333-004 p-000121212 267 o-000008888
333-005 p-000123456 N/C o-000002222
333-005 p-000456789 99999 o-000033333
答案 0 :(得分:2)
在这种情况下,我更喜欢使用CROSS APPLY
来计算即时计数作为派生集,并更喜欢使用sql:column()
来读取与位置相关的 节点通过 position谓词。
declare @xml xml =
N'<module mod-id="333">
<title>NNN NNNNN NNNNN</title>
<data-code>
<code-id>333-004</code-id>
<description>XXX XXX XXXXXXXX XXX X XXXXXXXXXXXXXXXX</description>
<applic>
<p32>
<condition cond-id="o-000008888">
<ctext> NNN NNNNNNNNN NN NNNNN NNNNNNNNN NN</ctext>
</condition>
<m234 domicile="all" ver-start="4.40" target-ver="4.40" vocation="all">
<value>
<price-container pwdb-id="p-000121212">267</price-container>
<weight-container pwdb-id="w-000676767">0/40</weight-container>
</value>
</m234>
</p32>
</applic>
</data-code>
<data-code>
<code-id>333-005</code-id>
<description>NNNNNNNNNNNNN NNNNNNNNNN NNNNN N NNNN N NNN NNNNNNNN</description>
<applic>
<p32>
<condition cond-id="o-000002222">
<ctext> NNNNNN NNNNN XXXX NNNN XXXX NNNNNNNN XXXXXXXX </ctext>
</condition>
<m234 domicile="all" ver-start="4.40" target-ver="4.40" vocation="all">
<value>
<price-container pwdb-id="p-000123456">N/C</price-container>
<weight-container pwdb-id="w-000234567">0/0</weight-container>
</value>
</m234>
<condition cond-id="o-000033333">
<ctext> Price with DC 622-005 , DC 622-197, , and DC 622-292 </ctext>
</condition>
<m234 domicile="all" ver-start="4.80" target-ver="4.80" vocation="all">
<value>
<price-container pwdb-id="p-000456789">99999</price-container>
<weight-container pwdb-id="w-000789012">0/0</weight-container>
</value>
</m234>
</p32>
</applic>
</data-code>
</module>';
-查询
SELECT A.dc.value('(code-id/text())[1]','nvarchar(100)') AS data_code
,A.dc.value('(applic/p32/m234[sql:column("Nmbr")]/value/price-container/@pwdb-id)[1]','nvarchar(100)') AS pwdb_id
,A.dc.value('(applic/p32/m234[sql:column("Nmbr")]/value/price-container/text())[1]','nvarchar(100)') AS [text]
,A.dc.value('(applic/p32/condition[sql:column("Nmbr")]/@cond-id)[1]','nvarchar(100)') AS cond_id
FROM @xml.nodes('/module/data-code') A(dc)
CROSS APPLY(SELECT TOP(A.dc.value('count(applic/p32/condition)','int')) ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) FROM master..spt_values) B(Nmbr);
结果
data_code pwdb_id text cond_id
333-004 p-000121212 267 o-000008888
333-005 p-000123456 N/C o-000002222
333-005 p-000456789 99999 o-000033333
简而言之:
我们使用.nodes()
来获取重复的<data-code>
节点。
现在,我们对CROSS APPLY
使用一个技巧:这将返回从1到n的列表作为派生集,其中n是<condition>
节点的数量。
如您所见,我可以使用APPLY
中的数字(由sql:column("Nmbr")
返回)。这会将condition[1]
与m234[1]
一起选择,并将condition[2]
与m234[2]
一起选择,依此类推。
使用向后导航../
和建议的<<
往往会很慢...
答案 1 :(得分:1)
您可以计算每个CROSS APPLY的行号并进行关联,如下所示:
SELECT x1.data_code, x1.pwdb_id, x1.text, x2.cond_id
FROM @xml.nodes('/module/data-code/applic/p32') as Xtble(datanode)
CROSS APPLY (
SELECT ROW_NUMBER() OVER (ORDER BY price) AS RowNum1,
price.value('(../../../../../code-id)[1]', 'varchar(50)') as data_code,
price.value('@pwdb-id', 'varchar(50)') as pwdb_id,
price.value('(text())[1]', 'varchar(50)') as text
FROM Xtble.datanode.nodes('m234/value/price-container') as Xtble2(price)
) x1
CROSS APPLY (
SELECT ROW_NUMBER() OVER (ORDER BY cond) AS RowNum2,
cond.value('(@cond-id) [1]', 'varchar(50)') as cond_id
FROM Xtble.datanode.nodes('condition') as Xtble3(cond)
) x2
WHERE x1.RowNum1=x2.RowNum2
答案 2 :(得分:1)
您可以使用<<
来获取一组先前的节点,并使用last()
来获取其中的最后一个节点。
select D.X.value('(code-id/text())[1]', 'varchar(50)') as data_code,
M.X.value('(value/price-container/@pwdb-id)[1]', 'varchar(50)') as pwdb_id,
M.X.value('(value/price-container/text())[1]', 'varchar(50)') as text,
M.X.value('(for $n in ../* where $n << . return $n)[last()]/@cond-id', 'varchar(50)')
from @xml.nodes('/module/data-code') as D(X)
cross apply D.X.nodes('applic/p32/m234') as M(X)