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

Manipulating XML Nodes in SQL (Merging nodes)

在SQL服务器中,如何将一组节点合并为一个?以下面的 XML 为例。我怎样才能从下面的格式转到在单个 'Attributes' 节点下有多个 'Attribute' 节点?

<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>

这是 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')