Select 某些重复 XML 节点在各个级别的名称和重复子节点作为来自所述节点内的行
Select certain repeating XML node by name at various levels & repeating sub-nodes as rows from within said node
采用以下简化的XML:
(来自第 3 方行业批发商数据提供商的非常昂贵(且大)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>
我的任务是生成以下输出:
事实证明这是极其困难的,原因有二:
您会注意到 <product>
3623949 存在于 Groups/Group/Group/Group/
(组的 3 层)中,而 <product>
3265725 存在于 Groups/Group/
(1 层)中组的)-我需要 select 所有 <product>
节点,无论它们的嵌套级别如何(理想情况下,只要父节点 = <Group>
)
注意 <product>
中的 <Other_Codes>
节点 - 我需要 select 重复子节点 (Code_Description & Code_Value)作为两个单独的列,但还要注意 <Other_Codes>
中可能有任意数量的 <Other_Code>
节点,我需要 select 它们全部(呈现 [i] 符号无用)
我已尽力使用 TSQL OPENXML
获取此数据,但我能想到的唯一方法是为各种 Group/Group/ levels 并且我还必须使用 [0] 符号对 Other_Code 的出现次数进行硬编码 - 考虑到它们的可变性质;错了。
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 服务器2008、2008 R2 和 SQL Server 2014 可供我们使用,但非 SQL 解决方案也会有所帮助 - 我们在这方面确实遇到了障碍。
所以你真正想要做的是让你的选择语句成为 //Other_Codes
- 双正斜杠表示你想要每个 Other_Codes
节点,无论它在层次结构中的位置如何,给你一个每个 Other_Codes
节点的行。然后,您可以指定 PipCode
为 ../../Pip_code
,当然假设此层次结构对于这部分也不会一直更改(但这在语义上有何意义?)。
这个:
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
采用以下简化的XML:
(来自第 3 方行业批发商数据提供商的非常昂贵(且大)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>
我的任务是生成以下输出:
事实证明这是极其困难的,原因有二:
您会注意到
<product>
3623949 存在于Groups/Group/Group/Group/
(组的 3 层)中,而<product>
3265725 存在于Groups/Group/
(1 层)中组的)-我需要 select 所有<product>
节点,无论它们的嵌套级别如何(理想情况下,只要父节点 =<Group>
)注意
<product>
中的<Other_Codes>
节点 - 我需要 select 重复子节点 (Code_Description & Code_Value)作为两个单独的列,但还要注意<Other_Codes>
中可能有任意数量的<Other_Code>
节点,我需要 select 它们全部(呈现 [i] 符号无用)
我已尽力使用 TSQL OPENXML
获取此数据,但我能想到的唯一方法是为各种 Group/Group/ levels 并且我还必须使用 [0] 符号对 Other_Code 的出现次数进行硬编码 - 考虑到它们的可变性质;错了。
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 服务器2008、2008 R2 和 SQL Server 2014 可供我们使用,但非 SQL 解决方案也会有所帮助 - 我们在这方面确实遇到了障碍。
所以你真正想要做的是让你的选择语句成为 //Other_Codes
- 双正斜杠表示你想要每个 Other_Codes
节点,无论它在层次结构中的位置如何,给你一个每个 Other_Codes
节点的行。然后,您可以指定 PipCode
为 ../../Pip_code
,当然假设此层次结构对于这部分也不会一直更改(但这在语义上有何意义?)。
这个:
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