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

两次CROSS APPLY致重复结果,求无需DISTINCT的解决办法

避免CROSS APPLY拆分关联后的数据重复问题

问题场景

现有XYZ表数据如下:

Id  Name   ssids
1    a1    1,2
2    a2    3
3    a3    4
4    a4    5

执行以下SQL查询,试图通过两次CROSS APPLY拆分ssids字段和参数值并关联,结果出现重复记录,且不想使用DISTINCT去重:

declare @Paravalue varchar(500)='1,2,3'

select t.*
from XYZ  t
cross apply string_split(t.ssids, ',') ColumnIds
cross apply string_split(@Paravalue, ',') paraId
where paraId.value = ColumnIds.value 

当前输出(存在重复)

Id  Name   ssids
 1    a1    1,2
 1    a1    1,2
 2    a2    3

期望输出(无重复,不使用DISTINCT)

Id  Name   ssids
1    a1    1,2
2    a2    3

问题原因

两次CROSS APPLY会生成笛卡尔积:

  • 对于Id=1的记录,string_split(t.ssids, ',')拆分出2行(值为1、2);string_split(@Paravalue, ',')拆分出3行(值为1、2、3)。
  • 过滤匹配后,会得到2条匹配结果(1匹配1、2匹配2),因此这条记录会被输出2次,最终导致重复。
  • 实际需求是只要记录的ssids中存在任意一个值在参数列表内,就保留该记录一次,而非每个匹配值都输出一次。

解决方案

方案1:使用EXISTS子查询(推荐,性能更优)

通过EXISTS判断当前记录是否存在匹配的拆分值,只要存在就返回该记录一次:

declare @Paravalue varchar(500)='1,2,3'

select t.*
from XYZ t
where exists (
    select 1
    from string_split(t.ssids, ',') ColumnIds
    where ColumnIds.value in (select value from string_split(@Paravalue, ','))
)

方案2:单次CROSS APPLY结合GROUP BY

通过GROUP BY将同一记录的多个匹配结果合并为一条,效果等同于去重但无需使用DISTINCT:

declare @Paravalue varchar(500)='1,2,3'

select t.Id, t.Name, t.ssids
from XYZ t
cross apply string_split(t.ssids, ',') ColumnIds
where ColumnIds.value in (select value from string_split(@Paravalue, ','))
group by t.Id, t.Name, t.ssids

方案3:CROSS APPLY结合TOP 1

通过子查询判断是否存在匹配,只要存在就返回一个标记,从而确保主表记录只输出一次:

declare @Paravalue varchar(500)='1,2,3'

select t.*
from XYZ t
cross apply (
    select top 1 1
    from string_split(t.ssids, ',') ColumnIds
    inner join string_split(@Paravalue, ',') paraId 
        on ColumnIds.value = paraId.value
) as MatchCheck

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 14:12:03