Sql server 按不同级别的名称选择某些重复的XML节点&;从所述节点中将子节点作为行重复
以以下简化的XML为例: (摘自第三方行业批发商数据提供商提供的一个非常昂贵(而且很大)的XML产品提要,即我无法控制其模式/格式/内容) 我的任务是生成以下输出: 事实证明,这是极其困难的,原因有两个:Sql server 按不同级别的名称选择某些重复的XML节点&;从所述节点中将子节点作为行重复,sql-server,xml,sql-server-openxml,Sql Server,Xml,Sql Server Openxml,以以下简化的XML为例: (摘自第三方行业批发商数据提供商提供的一个非常昂贵(而且很大)的XML产品提要,即我无法控制其模式/格式/内容) 我的任务是生成以下输出: 事实证明,这是极其困难的,原因有两个: 您会注意到3623949存在于组/组/组/组/(3级组)中,而3265725存在于组/组/(1级组)中-我需要选择所有节点,无论其嵌套级别如何(理想情况下是在父节点=时) 请注意中的节点-我需要选择重复的子节点(code\u Description&code\u Value)作为两个独立的列
3623949存在于组/组/组/组/
(3级组)中,而
3265725存在于组/组/
(1级组)中-我需要选择所有
节点,无论其嵌套级别如何(理想情况下是在父节点=
时)
中的
节点-我需要选择重复的子节点(code\u Description&code\u Value)作为两个独立的列,但还要注意
中可能有任意数量的
节点,我需要将它们全部选中(使[I]符号无效)OPENXML
获取这些数据,但我能想到的唯一方法是为不同的组/组/级别复制代码,并且我还必须使用[0]符号硬编码一组其他_代码的出现次数,这是由于它们的变量性质;这是错误的
SELECT *
FROM OPENXML (@idoc, 'Company/Brand/Groups/Group/Product',2)
WITH (
PIP_code CHAR (20) 'Pip_code',
OtherCodeType CHAR (20) 'Other_Codes/Other_Code[1]/Code_Description',
OtherCodeValue CHAR (30) 'Other_Codes/Other_Code[1]/Code_Value',
OtherCodeType2 CHAR (20) 'Other_Codes/Other_Code[2]/Code_Description',
OtherCodeValue2 CHAR (30) 'Other_Codes/Other_Code[2]/Code_Value',
OtherCodeType3 CHAR (20) 'Other_Codes/Other_Code[3]/Code_Description',
OtherCodeValue3 CHAR (30) 'Other_Codes/Other_Code[3]/Code_Value'
)
我们更愿意在TSQL中执行此操作(因为该XML文件已经在那里处理,用于其他与此处不相关的节点和路径),我们可以使用SQL Server 2008、2008 R2和SQL Server 2014,但是非SQL解决方案也会有帮助-我们在这一点上确实遇到了困难。因此,您真正想要做的是将选择语句设置为
//其他\u代码
-双正斜杠表示您需要每个其他\u代码
节点,而不管其在层次结构中的位置,为每个其他\u代码节点提供一行。然后,您可以指定PipCode
为。/../Pip\u code
,当然,假设此部分的层次结构也不会一直更改(但这在语义上有何意义?)
这:
产生以下结果:
PipCode Code_Description Code_Value
-----------------------------------------------------------------
3623949 EAN 5013158781351
3623949 shipper EAN 503158781443
3623949 AMPP 19192411000001107
3623949 AMPP Manf 2061801000001104
3265725 Outer EAN 5013158776531
3265725 AMPP 11521811000001106
3265725 AMPP Manf 2061801000001104
3265725 EAN 5013158776500
先生,您是一个天才。或者您是一个比SQL更习惯XSLT的人;)很乐意帮忙
DECLARE @doc xml = '<Company>
<Code>7786</Code>
<Brand>
<!-- /../ -->
<Groups>
<Group>
<!-- /../ -->
<Group>
<!-- /../ -->
<Group>
<!-- /../ -->
<Product>
<Pip_code>3623949</Pip_code>
<!-- /../ -->
<Other_Codes>
<Other_Code>
<Code_Description>EAN</Code_Description>
<Code_Value>5013158781351</Code_Value>
</Other_Code>
<Other_Code>
<Code_Description>shipper EAN</Code_Description>
<Code_Value>503158781443</Code_Value>
</Other_Code>
<Other_Code>
<Code_Description>AMPP</Code_Description>
<Code_Value>19192411000001107</Code_Value>
</Other_Code>
<Other_Code>
<Code_Description>AMPP Manf</Code_Description>
<Code_Value>2061801000001104</Code_Value>
</Other_Code>
</Other_Codes>
</Product>
</Group>
</Group>
</Group>
</Groups>
</Brand>
<Brand>
<!-- /../ -->
<Groups>
<Group>
<!-- /../ -->
<Product>
<Pip_code>3265725</Pip_code>
<!-- /../ -->
<Other_Codes>
<Other_Code>
<Code_Description>Outer EAN</Code_Description>
<Code_Value>5013158776531</Code_Value>
</Other_Code>
<Other_Code>
<Code_Description>AMPP</Code_Description>
<Code_Value>11521811000001106</Code_Value>
</Other_Code>
<Other_Code>
<Code_Description>AMPP Manf</Code_Description>
<Code_Value>2061801000001104</Code_Value>
</Other_Code>
<Other_Code>
<Code_Description>EAN</Code_Description>
<Code_Value>5013158776500</Code_Value>
</Other_Code>
</Other_Codes>
</Product>
</Group>
</Groups>
</Brand>
</Company>';
DECLARE @idoc int;
exec sp_xml_preparedocument @idoc OUTPUT, @doc;
SELECT *
FROM OPENXML(@idoc, '//Other_Code',1)
WITH (
PipCode CHAR (20) '../../Pip_code',
Code_Description CHAR(20) 'Code_Description',
Code_Value CHAR (30) 'Code_Value'
)
PipCode Code_Description Code_Value
-----------------------------------------------------------------
3623949 EAN 5013158781351
3623949 shipper EAN 503158781443
3623949 AMPP 19192411000001107
3623949 AMPP Manf 2061801000001104
3265725 Outer EAN 5013158776531
3265725 AMPP 11521811000001106
3265725 AMPP Manf 2061801000001104
3265725 EAN 5013158776500