T-SQL:交叉应用;行项目上的迭代次数过多
在分解了一些重要的Xml之后,我几乎得到了想要的结果——但是在查看结果之后,我发现在解析的一个部分中,我无法轻松解决迭代每个副标题的所有行详细信息的模式——因此,与其为所有行项目总共写出3条记录,我为每个sub写了三行项目——假设我有两行。我总共得到了6分-(在下面的代码中,我将该模式提炼为通用标题/副标题/细节关系模型T-SQL:交叉应用;行项目上的迭代次数过多,sql,sql-server,tsql,xml-parsing,identifier,Sql,Sql Server,Tsql,Xml Parsing,Identifier,在分解了一些重要的Xml之后,我几乎得到了想要的结果——但是在查看结果之后,我发现在解析的一个部分中,我无法轻松解决迭代每个副标题的所有行详细信息的模式——因此,与其为所有行项目总共写出3条记录,我为每个sub写了三行项目——假设我有两行。我总共得到了6分-(在下面的代码中,我将该模式提炼为通用标题/副标题/细节关系模型 DECLARE @MetroXML xml SET @MetroXML = '<Header> <col1>Con
DECLARE @MetroXML xml
SET @MetroXML =
'<Header>
<col1>Conoco</col1>
<col2>ORD-1111</col2>
<SubHeaders>
<SubHeader>
<col1>Dallas</col1>
<col2>BOL-2213</col2>
<Details>
<Detail>
<col1>Diesel</col1>
<col2>7600.00</col2>
</Detail>
</Details>
</SubHeader>
</SubHeaders>
<SubHeaders>
<SubHeader>
<col1>Fort Worth</col1>
<col2>BOL-2216</col2>
<Details>
<Detail>
<col1>Ethanol</col1>
<col2>1852.00</col2>
</Detail>
<Detail>
<col1>Unleaded</col1>
<col2>900.00</col2>
</Detail>
</Details>
</SubHeader>
</SubHeaders>
</Header>';
INSERT INTO [scratch].GenericHeader
SELECT T.c.value('col1[1]','varchar(10)') AS 'col1',
T.c.value('col2[1]','varchar(10)') AS 'col2'
FROM @MetroXML.nodes('/Header') T(c);
INSERT [scratch].GenericSubHeader
(id,col1,col2)
SELECT
h.id,
n.x.value('col1[1]','varchar(10)') AS 'col1',
n.x.value('col2[1]','varchar(10)') AS 'col2'
FROM [scratch].GenericHeader h
CROSS APPLY @MetroXML.nodes('/Header/SubHeaders/SubHeader') n(x);
INSERT [scratch].GenericDetail
(id,subid,col1,col2)
SELECT
s.id,
s.subid,
n.x.value('col1[1]','varchar(10)') AS 'col1',
n.x.value('col2[1]','varchar(10)') AS 'col2'
FROM [scratch].GenericSubHeader s
CROSS APPLY @MetroXML.nodes('/Header/SubHeaders/SubHeader/Details/Detail') as n(x);
select * from [scratch].GenericHeader
where id = 24;
select * from [scratch].GenericSubHeader
where id = 24;
select * from [scratch].GenericDetail
where id = 24;
我想要的是:
id|subid|detid|col1 |col2
--------------------------------
24|44 |22 |Diesel |7600.00
24|48 |23 |Ethanol |1852.00
24|48 |24 |Unleaded |900.00
获得重复行的原因是对
GenericSubHeader
中每行的整个XML使用交叉应用。您必须找到一种方法,将GenericSubHeader
中生成的ID
和GenericSubHeader
中生成的subid
映射到XML的相关部分
如果您使用的是SQL Server 2008或更高版本,则可以创建一个表变量,该变量保存生成的id和所属的xml子节点
declare @GH table
(
id int,
sub xml
);
merge scratch.GenericHeader as T
using
(
select T.c.value('col1[1]','varchar(10)'),
T.c.value('col2[1]','varchar(10)'),
T.c.query('SubHeaders')
from @MetroXML.nodes('/Header') T(c)
) as S(col1, col2, sub)
on 0 = 1
when not matched then
insert (col1, col2) values(S.col1, S.col2)
output inserted.id, S.sub into @GH;
declare @GSH table
(
id int,
subid int,
det xml
);
merge scratch.GenericSubHeader as T
using
(
select h.id,
n.x.value('col1[1]','varchar(10)'),
n.x.value('col2[1]','varchar(10)'),
n.x.query('Details')
from @GH as h
cross apply h.sub.nodes('/SubHeaders/SubHeader') n(x)
) as S(id, col1, col2, det)
on 0 = 1
when not matched then
insert (id, col1, col2) values (S.id, S.col1, S.col2)
output inserted.id, inserted.subid, S.det into @GSH;
insert into scratch.GenericDetail(id, subid, col1, col2)
select s.id,
s.subid,
n.x.value('col1[1]','varchar(10)') AS 'col1',
n.x.value('col2[1]','varchar(10)') AS 'col2'
from @GSH as s
cross apply s.det.nodes('/Details/Detail') as n(x);
把你得到的放在问题中,而不是评论中谢谢!谢谢!谢谢!最后一个结合tsql的算法不仅有效,而且高效、清晰、实用!
declare @GH table
(
id int,
sub xml
);
merge scratch.GenericHeader as T
using
(
select T.c.value('col1[1]','varchar(10)'),
T.c.value('col2[1]','varchar(10)'),
T.c.query('SubHeaders')
from @MetroXML.nodes('/Header') T(c)
) as S(col1, col2, sub)
on 0 = 1
when not matched then
insert (col1, col2) values(S.col1, S.col2)
output inserted.id, S.sub into @GH;
declare @GSH table
(
id int,
subid int,
det xml
);
merge scratch.GenericSubHeader as T
using
(
select h.id,
n.x.value('col1[1]','varchar(10)'),
n.x.value('col2[1]','varchar(10)'),
n.x.query('Details')
from @GH as h
cross apply h.sub.nodes('/SubHeaders/SubHeader') n(x)
) as S(id, col1, col2, det)
on 0 = 1
when not matched then
insert (id, col1, col2) values (S.id, S.col1, S.col2)
output inserted.id, inserted.subid, S.det into @GSH;
insert into scratch.GenericDetail(id, subid, col1, col2)
select s.id,
s.subid,
n.x.value('col1[1]','varchar(10)') AS 'col1',
n.x.value('col2[1]','varchar(10)') AS 'col2'
from @GSH as s
cross apply s.det.nodes('/Details/Detail') as n(x);