You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为SQL Server XML节点生成关联HeadId,实现数据拆分?

MS SQL Server XML拆分:让Items表HeadID匹配原Item节点

我们有如下MS SQL Server格式的XML数据:

<Features>
  <Item>
   <Description>First Descr.</Description>
   <Comment>First comment</Comment>
   <C0001>12</C0001>
   <C0002>23</C0002>
  </Item>   
  <Item>
   <Description>Second Descr.</Description>
   <Comment>Second comment</Comment>
   <C0001>212</C0001>
   <C0002>223</C0002>
   <C0003>323</C0003>
  </Item>   
</Features>

需要将其拆分存储到Head和Items两个独立表中,期望结果如下:

Head表:

HeadID |  Description   | Comment 
1      |  First Descr.  | First comment
2      |  Second Descr. | Second comment

Items表:

HeadID    | Name  | ResValue
1         | C0001 | 12
1         | C0002 | 23
2         | C0001 | 212
2         | C0002 | 223
2         | C0003 | 323

目前用OPENXML结合ROW_NUMBER()生成Head表的HeadID是正确的,但处理Items表时,现有代码生成的HeadID是连续递增的1、2、3、4、5,无法和原Item节点对应。现有Items表处理代码:

SELECT 
    ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as HeadId,
    unpvt.[Name],
    TRY_PARSE(REPLACE(unpvt.ResValue,',','.') AS DECIMAL(12, 6)) as ResValue
    FROM OPENXML (@idoc, '/Features/Item', 1)
        WITH (
            Description nvarchar(255) 'Description',
            Comment nvarchar(4000) 'Comment',
            C0001 nvarchar(20) 'C0001', 
            C0002 nvarchar(20) 'C0002', 
            C0003 nvarchar(20) 'C0003'
        ) x
        UNPIVOT ([ResValue] FOR [Name] IN (C0001,C0002,C0003)) AS unpvt
    WHERE TRY_PARSE(REPLACE(unpvt.ResValue,',','.') AS DECIMAL(12, 6)) <> 0

解决方案

问题出在你把ROW_NUMBER()放在了UNPIVOT之后,这时候它会对所有展开后的行(共5行)生成连续ID,而不是按原Item节点分组。正确的做法是先在OPENXML返回的每个Item节点层面生成对应的HeadID,再执行UNPIVOT,这样每个展开后的行都会继承所属Item的HeadID。

修改后的核心代码

SELECT 
    x.HeadId,
    unpvt.[Name],
    TRY_PARSE(REPLACE(unpvt.ResValue,',','.') AS DECIMAL(12, 6)) as ResValue
FROM (
    -- 先为每个Item节点生成对应的HeadID
    SELECT 
        ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) as HeadId,
        C0001, C0002, C0003
    FROM OPENXML (@idoc, '/Features/Item', 1)
        WITH (
            C0001 nvarchar(20) 'C0001', 
            C0002 nvarchar(20) 'C0002', 
            C0003 nvarchar(20) 'C0003'
        )
) x
UNPIVOT ([ResValue] FOR [Name] IN (C0001,C0002,C0003)) AS unpvt
WHERE TRY_PARSE(REPLACE(unpvt.ResValue,',','.') AS DECIMAL(12, 6)) <> 0

可选:关联Head表确保ID一致

如果已经生成了Head表,也可以通过Description和Comment关联获取HeadID,彻底保证两个表的ID完全匹配:

SELECT 
    h.HeadId,
    unpvt.[Name],
    TRY_PARSE(REPLACE(unpvt.ResValue,',','.') AS DECIMAL(12, 6)) as ResValue
FROM OPENXML (@idoc, '/Features/Item', 1)
    WITH (
        Description nvarchar(255) 'Description',
        Comment nvarchar(4000) 'Comment',
        C0001 nvarchar(20) 'C0001', 
        C0002 nvarchar(20) 'C0002', 
        C0003 nvarchar(20) 'C0003'
    ) x
UNPIVOT ([ResValue] FOR [Name] IN (C0001,C0002,C0003)) AS unpvt
JOIN Head h ON h.Description = x.Description AND h.Comment = x.Comment
WHERE TRY_PARSE(REPLACE(unpvt.ResValue,',','.') AS DECIMAL(12, 6)) <> 0

内容的提问来源于stack exchange,提问作者Zoltan Hernyak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 01:41:31