在SQL中操作XML节点(合并节点)

时间:2016-12-09 20:49:22

标签: sql-server xml sqlxml

在SQL Server中,如何将节点集合合并为一个节点?以下面的XML为例。如何从下面的格式转变为在单个“属性”节点下拥有多个“属性”节点?

<Thing>
    <Id>160</Id>
    <Attributes>
        <Attribute>
            <Id>2</Id>
            <Values>
                <Value>94</Value>
            </Values>
        </Attribute>
    </Attributes> -- **how can i remove this**
    <Attributes> -- **and this**
        <Attribute>
            <Id>4</Id>
            <Values>
                <Value>103</Value>
            </Values>
        </Attribute>
    </Attributes>
</Thing>

编辑:我对这个问题有第二部分 鉴于此输入:

<Thing>
    <Id>160</Id>
    <Attributes>
        <Attribute>
            <Id>2</Id>
            <Values>
                <Value>94</Value>
            </Values>
        </Attribute>
    </Attributes>
    <Attributes>
        <Attribute>
            <Id>2</Id>
            <Values>
                <Value>103</Value>
            </Values>
        </Attribute>
    </Attributes>
    <Attributes>
        <Attribute>
            <Id>4</Id>
            <Values>
                <Value>106</Value>
            </Values>
        </Attribute>
    </Attributes>
</Thing>

如何合并属性以实现此输出,其中值也根据匹配的ID合并?

<Thing>
    <Id>160</Id>
    <Attributes>
        <Attribute>
            <Id>2</Id>
            <Values>
                <Value>94</Value>
                <Value>103</Value>
            </Values>
        </Attribute>
        <Attribute>
            <Id>4</Id>
            <Values>
                <Value>106</Value>
            </Values>
        </Attribute>
    </Attributes>
</Thing>

1 个答案:

答案 0 :(得分:3)

这是FLWOR-XQuery的方法:

DECLARE @xml XML=
N'<Thing>
    <Id>160</Id>
    <Attributes>
        <Attribute>
            <Id>2</Id>
            <Values>
                <Value>94</Value>
            </Values>
        </Attribute>
    </Attributes> 
    <Attributes> 
        <Attribute>
            <Id>4</Id>
            <Values>
                <Value>103</Value>
            </Values>
        </Attribute>
    </Attributes>
</Thing>';

- 查询将根据您的需要重新创建XML:

SELECT @xml.query
(
N'
    <Thing>
    {Thing/Id}
    <Attributes>
    {
        for $a in //Attributes/Attribute
        return $a
    }
    </Attributes>
    </Thing>
'
)

结果

<Thing>
  <Id>160</Id>
  <Attributes>
    <Attribute>
      <Id>2</Id>
      <Values>
        <Value>94</Value>
      </Values>
    </Attribute>
    <Attribute>
      <Id>4</Id>
      <Values>
        <Value>103</Value>
      </Values>
    </Attribute>
  </Attributes>
</Thing>

更新您的后续问题

在这种情况下,我会切碎并重新创建完整的XML:

DECLARE @xml XML=
N'<Thing>
<Id>160</Id>
<Attributes>
    <Attribute>
        <Id>2</Id>
        <Values>
            <Value>94</Value>
        </Values>
    </Attribute>
</Attributes>
<Attributes>
    <Attribute>
        <Id>2</Id>
        <Values>
            <Value>103</Value>
        </Values>
    </Attribute>
</Attributes>
<Attributes>
    <Attribute>
        <Id>4</Id>
        <Values>
            <Value>106</Value>
        </Values>
    </Attribute>
</Attributes>
</Thing>';


WITH attribs AS
(
    SELECT a.value('Id[1]','int') AS Id
          ,v.value('.','int') AS Value
    FROM @xml.nodes('/Thing/Attributes/Attribute') AS A(a)
    OUTER APPLY a.nodes('Values/Value') AS B(v)
)
,distinctAttribIDs AS
(
    SELECT DISTINCT Id FROM attribs
)
SELECT @xml.value('(/Thing/Id)[1]','int') AS Id
      ,(
            SELECT da.Id
                  ,(
                    SELECT a.Value
                    FROM attribs AS a
                    WHERE a.Id=da.Id
                    FOR XML PATH(''), ROOT('Values'),TYPE
                   ) 
            FROM distinctAttribIDs AS da
            FOR XML PATH('Attribute'),ROOT('Attributes'),TYPE
       )
FOR XML PATH('Thing')