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

如何从XML表列提取多层级关联数据?SQL查询优化求助

问题:从XML列提取多层关联数据的SQL查询优化

我有一张包含XML列的数据库表,XML结构如下:

<option> 
  <OptionName>Option 1</OptionName> 
  <grant> 
    <GrantName>Grant 1</GrantName> 
    <schedules> 
      <schedule> 
        <scheduleID></scheduleID> 
        <scheduleName></scheduleName> 
        <scheduleDate>1/1/2018</scheduleDate> 
        <scheduleAmount></scheduleAmount> 
      </schedule> 
      <schedule> 
        <scheduleID></scheduleID> 
        <scheduleName></scheduleName> 
        <scheduleDate>2/1/2018</scheduleDate> 
        <scheduleAmount></scheduleAmount> 
      </schedule> 
      <schedule> 
        <scheduleID></scheduleID> 
        <scheduleName></scheduleName> 
        <scheduleDate>3/1/2018</scheduleDate> 
        <scheduleAmount></scheduleAmount> 
      </schedule> 
    </schedules> 
  </grant> 
  <grant> 
    <GrantName>Grant 2</GrantName> 
    <schedules> 
      <schedule> 
        <scheduleID></scheduleID> 
        <scheduleName></scheduleName> 
        <scheduleDate>1/1/2019</scheduleDate> 
        <scheduleAmount></scheduleAmount> 
      </schedule> 
      <schedule> 
        <scheduleID></scheduleID> 
        <scheduleName></scheduleName> 
        <scheduleDate>2/1/2019</scheduleDate> 
        <scheduleAmount></scheduleAmount> 
      </schedule> 
      <schedule> 
        <scheduleID></scheduleID> 
        <scheduleName></scheduleName> 
        <scheduleDate>3/1/2019</scheduleDate> 
        <scheduleAmount></scheduleAmount> 
      </schedule> 
    </schedules> 
  </grant>
</option>

注:修正了原XML中闭合标签不匹配的问题(比如<GrantName>对应</Name>的错误,统一改成</GrantName>,还有<scheduleID>的闭合标签)

我希望通过SQL查询得到如下格式的结果:

OptionName | GrantName | ScheduleDate
Option 1   | Grant 1   | 1/1/2018
Option 1   | Grant 1   | 2/1/2018
Option 1   | Grant 1   | 3/1/2018
Option 1   | Grant 2   | 1/1/2019
Option 1   | Grant 2   | 2/1/2019
Option 1   | Grant 2   | 3/1/2019

目前我尝试的查询语句如下:

select 
  FactChange.Fact.value('(Option/OptionName)[1]','varchar(max)') OptionName,
  FactChange.Fact.value('(Option/Grant/GrantName)[1]', 'varchar(max)') grantName 
from FactChange(nolock)

但该语句仅能提取子节点的第一个值,无法获取全部关联数据,请求优化该SQL查询以得到预期结果。


解决方案

要提取XML中多层嵌套的关联数据,你需要用.nodes()方法来逐个展开<grant>和<schedule>节点,通过CROSS APPLY来关联这些层级,这样就能把每个Option下的每个Grant,再到每个Schedule都一一对应起来。

优化后的SQL语句如下:

select
  -- 提取OptionName,从根节点开始定位
  fc.Fact.value('(option/OptionName)[1]', 'varchar(max)') as OptionName,
  -- 从每个grant节点提取GrantName
  g.grantNode.value('(GrantName)[1]', 'varchar(max)') as GrantName,
  -- 从每个schedule节点提取ScheduleDate
  s.scheduleNode.value('(scheduleDate)[1]', 'varchar(max)') as ScheduleDate
from FactChange fc(nolock)
-- 展开所有grant节点
cross apply fc.Fact.nodes('option/grant') as g(grantNode)
-- 针对每个grant节点,展开其下的所有schedule节点
cross apply g.grantNode.nodes('schedules/schedule') as s(scheduleNode)

说明:

  1. fc.Fact.nodes('option/grant'):把XML列中的所有<grant>节点拆分成行,每个行对应一个grant节点,别名g(grantNode)。
  2. g.grantNode.nodes('schedules/schedule'):针对每个grant节点,再拆分其下的所有<schedule>节点,每个行对应一个schedule节点,别名s(scheduleNode)。
  3. 最后分别从根节点提取OptionName,从grant节点提取GrantName,从schedule节点提取ScheduleDate,这样就能得到所有层级的关联数据,完全匹配你想要的结果格式。

内容的提问来源于stack exchange,提问作者Richi Sharma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:21:56