SQL三表JOIN查询客户可采购供应商ID结果异常排查
问题原因
你这段SQL的逻辑从根上就写错了,两个硬伤:
- 关联逻辑完全错了:你从黑名单表T1出发做关联,还用
T3.id != T1.T3_id做右连条件,本质是做不等值匹配,会产生大量冗余匹配行。比如客户1在T1里有两条禁供记录(对应3、4两个供应商),右连T3的时候:供应商3会匹配到T1里T3_id=4的那条客户1的记录,供应商4会匹配到T1里T3_id=3的那条客户1的记录,等于两个禁供供应商全被漏进结果集了,再加上本来就允许采购的1、2,自然会出来重复的错误结果。 - 过滤条件位置不对:你把
T2.id = 1写在WHERE子句里,会把右连产生的空值行直接过滤掉,根本实现不了「排除禁供供应商」的效果。
至于你说查T2.id=2的时候结果正常,纯巧合:客户2在T1里只有1条禁供记录(对应供应商3),不存在同一个客户多条禁供记录交叉匹配的问题,结果刚好对而已,只要客户2的禁供记录超过1条,一样会出问题。
正确实现
需求本质很简单:查出所有供应商,排除掉和指定客户在黑名单里有匹配记录的就行,根本不需要关联T2(T1已经存了客户ID,要是需要校验客户是否真实存在再加T2关联即可),给三个常用写法:
写法1:NOT IN 语义最直观
SELECT id FROM T3 WHERE id NOT IN ( SELECT T3_id FROM T1 WHERE T2_id = 1 -- 替换成要查询的客户ID即可 )
写法2:NOT EXISTS 性能最优,生产环境推荐
SELECT t3.id FROM T3 t3 WHERE NOT EXISTS ( SELECT 1 FROM T1 t1 WHERE t1.T2_id = 1 -- 替换成要查询的客户ID AND t1.T3_id = t3.id )
写法3:左连接判空,逻辑和NOT EXISTS等价
SELECT t3.id FROM T3 t3 LEFT JOIN T1 t1 ON t1.T2_id = 1 -- 注意客户ID过滤条件要写在ON里,不能写在WHERE里 AND t1.T3_id = t3.id WHERE t1.T1_id IS NULL
验证
用你给的测试数据跑,查客户1的时候返回结果就是1、2,完全符合预期;查客户2的时候返回1、2、4,逻辑也正确。
内容的提问来源于stack exchange,提问作者Vinícius OA
相关产品推荐
相关产品推荐

