我必须每两周切碎一个XML文档。它符合NEMSIS 2标准,并且我有一个符合标准的数据库来保存信息。我已经成功构建了一个查询来导入所有一对一数据,但是我在切碎一对多数据时遇到了麻烦。
使用此演示数据:
declare @x xml
set @x =
'<EMSDataSet>
<Header>
<D01_01>abc</D01_01>
<Record>
<E01>
<E01_01>12345</E01_01>
<E01_02>678</E01_02>
</E01>
<E02>
<E02_01>123</E02_01>
<E02_09>295</E02_09>
<E02_09>296</E02_09>
</E02>
</Record>
<Record>
<E01>
<E01_01>67890</E01_01>
<E01_02>678</E01_02>
</E01>
<E02>
<E02_01>123</E02_01>
<E02_09>295</E02_09>
</E02>
</Record>
</Header>
</EMSDataSet>'
此查询正确返回正确的值01_01和第一个值02_09。但是,由于 Value()只能返回一个单例,因此我只能获得第一个值:
Query:
select
t.c.value('(E01/E01_01)[1]','varchar(max)') e01_01
,t.c.value('(E02/E02_09)[1]','varchar(max)') e02_09
from @x.nodes('EMSDataSet/Header/Record') t(c)
Returns:
e01_01 e02_09
------ ------
12345 295
此查询在其各自的行中返回两个值02_09的值,但没有对应的值01_01的值:
Query:
select
t2.c.value('.','varchar(max)') e02_09
from @x.nodes('EMSDataSet/Header/Record/E02/E02_09') t2(c)
Returns:
e02_09
-----
295
296
我需要完成的是合并结果,并将值02_09的两个值与在每一行上重复的值01_01合并。值01_01将充当数据库中的外键,引用特定的唯一事件。
e01_01 e02_09
------ ------
12345 295
12345 296
它似乎可能需要使用 Nodes()方法,可能还需要使用 Join ,但是我无法弄清楚语法来获取单一值01_01的值对每个值02_09的值重复此操作。
这些问题/答案到目前为止已经使我明白了:
Retrieve-all-child-nodes-from-a-parent-node-xml-sql-server
Returning multiple rows from querying XML column in SQL Server 2008
T-SQL Shred Second Level XML Nodes into Multiple Rows
Shred XML For Each Row in SQL Table
编辑: 在早期取得成功之后,我尝试遵循代码。但是,它没有从我的测试数据集中返回正确的36行(35条记录,重复两次e02_09的重复值),而是返回了1260条记录(36行* 35行)。
select *
from
(
select
t.c.value('(E01/E01_01)[1]','varchar(max)') e01_01
from @x.nodes('EMSDataSet/Header/Record') t(c)
) a
,
(
select
t2.c.value('.','varchar(max)') e02_09
from @x.nodes('EMSDataSet/Header/Record/E02/E02_09') t2(c)
) b
答案 0 :(得分:0)
我能够实现的最佳答案是基于以下blog post by Adam Machanic:
select
e01_01
,e02_09
from
(select
dense_rank() over (order by b_node) unique_b_node
,c_node.value('./text()[1]','varchar(max)') e02_09
from @x.nodes('/EMSDataSet/Header/Record') b(b_node)
cross apply b.b_node.nodes('./E02/E02_09') c(c_node)
) a
join
(select
dense_rank() over (order by b2.b_node) unique_b_node
,c_node.value('text()[1]','varchar(max)') e01_01
from @x.nodes('/EMSDataSet/Header/Record') b2(b_node)
cross apply b2.b_node.nodes('./E01/E01_01') c2(c_node)
) b
on a.unique_b_node = b.unique_b_node