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

SQL查询单表重复记录并排除另一表匹配值的优化方案咨询

SQL优化与边界问题解答

基础信息梳理

测试表数据

  • Table1:
col1  col2
-------------
a1    b1
a2    b1
a3    b2
a4    b3
a5    b3
a5    b4
a5    b2
  • Table2:
col2  col3
----------
b1    c1
b4    c2

需求与现有实现

原有逻辑为查询Table1中col2字段存在重复的所有记录,对应SQL:

SELECT x.col1,x.col2
  FROM table1 x
  JOIN (SELECT t.col2
          FROM table1 t
      GROUP BY t.col2
        HAVING COUNT(t.col2) > 1) y ON y.col2 = x.col2

需要新增逻辑:排除上述结果中col2值存在于Table2的条目,预期输出:

col1  col2
----------
a3    b2
a4    b3
a5    b3
a5    b2 

当前使用NOT IN的实现可以跑通测试数据,但存在性能和鲁棒性问题。


问题1:性能更优的写法

有两类可落地的优化方案,性能均优于当前写法:

  • 过滤逻辑下推+NOT EXISTS替代NOT IN
    把对Table2的过滤逻辑提前到聚合子查询内部,先筛掉不需要的col2值,减少外层JOIN的数据量;同时用NOT EXISTS替代NOT IN,匹配到对应记录就终止扫描,在Table2.col2建索引时效率提升明显:
SELECT x.col1, x.col2
FROM table1 x
JOIN (
    SELECT t.col2
    FROM table1 t
    GROUP BY t.col2
    HAVING COUNT(t.col2) > 1
        AND NOT EXISTS (SELECT 1 FROM table2 t2 WHERE t2.col2 = t.col2)
) y ON y.col2 = x.col2
  • 窗口函数替代自连接(支持窗口函数的数据库适用)
    用窗口函数一次扫描表就计算出每个col2的重复次数,省掉聚合后自连接的步骤,大表场景下性能提升非常显著:
WITH col2_stat AS (
    SELECT 
        col1,
        col2,
        COUNT(*) OVER(PARTITION BY col2) AS repeat_cnt
    FROM table1
)
SELECT col1, col2
FROM col2_stat
WHERE repeat_cnt > 1
    AND NOT EXISTS (SELECT 1 FROM table2 t2 WHERE t2.col2 = col2_stat.col2)

问题2:NOT IN写法的边界风险

当前写法在特定场景下会返回完全不符合预期的结果,核心风险有两个:

  • NULL值导致结果全空
    如果Table2的col2字段存在NULL值,整个NOT IN的判断逻辑会失效。SQL中NULL代表未知值,当子查询返回的结果集包含NULL时,所有值与NULL做不等值判断的结果都是UNKNOWN,最终WHERE条件没有符合的记录,返回空结果,和预期完全偏差。
  • 隐式转换导致结果错误+性能下降
    如果table1.col2和table2.col2的字段类型、字符集、排序规则不一致,会触发隐式类型转换,一方面会导致字段上的索引失效,查询变慢;另一方面可能出现匹配逻辑错误,比如大小写规则不匹配导致该排除的记录没排除、不该排除的记录被过滤。

如果能从表结构层面保证Table2.col2有非空约束、且两个关联字段类型/字符集完全一致,NOT IN可以正常返回结果,但鲁棒性远低于NOT EXISTS写法。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 12:57:16