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

SQL Server 2012:无需CROSS APPLY从XML列筛选TextReadingId=1的ListId

问题背景

在SQL Server 2012环境中,存在如下结构的表tblStepList,其中Data列存储XML格式数据:

USE tempdb;
GO

-- DDL and sample data population, start
DROP TABLE IF EXISTS [dbo].[tblStepList];

CREATE TABLE [dbo].[tblStepList](
    [listid] [int],
    [Data] [xml] NOT NULL
);

INSERT INTO dbo.tblStepList (Listid, [Data]) VALUES
(1, N'<Steplist>
  <Step>
    <StepId>e36a3450-1c8f-44da-b4d0-58e5bfe2a987</StepId>
    <Rank>1</Rank>
    <IsComplete>false</IsComplete>
    <TextReadingId>10</TextReadingId>      
  </Step>
  <Step>
    <StepId>4078c1b1-71ea-4578-ba61-d2f6a5126ba1</StepId>
    <Rank>2</Rank>
    <TextReadingName>reading1</TextReadingName>
    <TextReadingId>12</TextReadingId>
  </Step>
</Steplist>'),
(2, N'<Steplist>
  <Step>
    <StepId>d9e42387-56e3-40a1-9698-e89c930d98d1</StepId>
    <Rank>1</Rank>
    <IsComplete>false</IsComplete>
    <TextReadingName>bug-8588_Updated3</TextReadingName>   
    <TextReadingId>0</TextReadingId>  
  </Step>
  <Step>
    <StepId>e5eaf947-24e1-4d3b-a92a-d6a90841293b</StepId>
    <Rank>2</Rank>
     <TextReadingId>1</TextReadingId>  
  </Step>
</Steplist>'),
(3, N'<Steplist>
  <Step>
    <StepId>d9e42387-56e3-40a1-9698-58e5bfe2a987</StepId>
    <Rank>1</Rank>
    <IsComplete>true</IsComplete>
    <TextReadingName>bug-8588_Updated3</TextReadingName>   
    <TextReadingId>1</TextReadingId>  
  </Step>
  <Step>
    <StepId>e5eaf947-24e1-4d3b-a92a-d2f6a5126ba1</StepId>
    <Rank>2</Rank>
     <TextReadingId>1</TextReadingId>  
  </Step>
</Steplist>');
-- DDL and sample data population, end

需求是筛选出Data列的XML中存在TextReadingId=1的ListId,预期结果为ListId 2、3。原使用CROSS APPLY的查询虽然可行,但大数据量下性能较差:

select  distinct Listid from
(
    SELECT 
        s.Listid,
        x.XmlCol.value('(TextReadingId)[1]', 'int') as [TextReadingId]
    FROM tblStepList s 
    CROSS APPLY s.Data.nodes('/Steplist/Step') x(XmlCol)
) a
where TextReadingId = 1

优化方案:使用XML的exist()方法

无需展开XML节点,直接利用SQL Server XML类型的exist()方法判断是否存在符合条件的节点,避免生成大量中间结果,大幅提升大数据量下的查询性能。

优化后的查询语句

SELECT Listid
FROM dbo.tblStepList
WHERE Data.exist('/Steplist/Step[TextReadingId = 1]') = 1;

原理说明

  • exist()方法接收XPath表达式作为参数,返回1表示XML中存在匹配的节点,返回0表示不存在。
  • XPath表达式/Steplist/Step[TextReadingId = 1]用于定位:在<Steplist>根节点下,找到包含<TextReadingId>值为1的<Step>节点。
  • 该查询直接在原表上过滤,无需展开所有<Step>节点,避免了CROSS APPLY带来的额外开销,尤其在数据量较大时性能优势明显。

内容的提问来源于stack exchange,提问作者Helen Araya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 20:24:23