能否用JOIN替换SQL查询中的NOT EXISTS?改写后结果异常求助
问题原因分析
你的改写逻辑核心错误是把过滤条件写在了LEFT JOIN的ON子句里,而非WHERE子句:
- 原
NOT EXISTS的逻辑是:筛选table1中,在table2里找不到product_id=1且doc_id=t1.id的记录。 - 你在LEFT JOIN的ON里加
table2.id IS NULL,这是在定义表的关联规则,意思是只关联table2中id为NULL的行(如果table2的id是主键,这类行根本不存在),导致这个LEFT JOIN相当于没做任何过滤,所有符合WHERE条件的table1行都被保留,结果数自然远多于原查询。
修正后的SQL写法
有两种贴合原逻辑的正确改写方式:
方式一:LEFT JOIN + WHERE过滤无匹配记录
把table2.id IS NULL移到WHERE子句,确保关联后没有匹配的table2记录:
SELECT t1.* FROM table1 as t1 LEFT OUTER JOIN table2 ON table2.doc_id = t1.id AND table2.product_id = 1 WHERE (t1.phone != "" OR t1.sms_phone != "") AND t1.docType in (1,2,3) AND table2.id IS NULL; -- 此处才是过滤无匹配table2记录的正确位置
注:建议选t1.*而非*,避免返回table2的NULL字段,和原查询结果保持一致
方式二:LEFT JOIN + DISTINCT(应对table2多匹配场景)
如果table2中可能存在多条匹配同一个t1.id的记录,原NOT EXISTS会自动忽略重复(只要存在就排除),而LEFT JOIN会先产生重复行再过滤,这种情况要加DISTINCT确保结果唯一:
SELECT DISTINCT t1.* FROM table1 as t1 LEFT OUTER JOIN table2 ON table2.doc_id = t1.id AND table2.product_id = 1 WHERE (t1.phone != "" OR t1.sms_phone != "") AND t1.docType in (1,2,3) AND table2.id IS NULL;
关键逻辑区别
NOT EXISTS是半连接:只要找到匹配记录就排除,不会产生重复行;- LEFT JOIN是全连接:会先生成所有可能的匹配行,再过滤掉有匹配的记录,若table2有多条匹配,必须用DISTINCT去重才能和原查询结果一致。
内容的提问来源于stack exchange,提问作者MD5
相关产品推荐
相关产品推荐

