求助:如何编写SQL查询无关联有效c记录的s表记录
求助:如何编写SQL查询无关联有效c记录的s表记录
首先得帮你梳理下需求的核心:我们要找的是所有不存在“活跃中间表记录关联到活跃c记录”的s,也就是三种情况:
- s完全没有关联任何cs记录
- s关联的cs都是已删除的(cs.del=1)
- s关联的活跃cs(cs.del=0)对应的c要么不存在,要么是已删除的(c.del=1)
先说说你原来查询的问题:你的SQL逻辑完全搞反了——你当前的WHERE条件是在筛选「有活跃cs/无cs,且有活跃c/无c」的记录,最后还要count>0,这其实是在找那些有有效关联的s,和你要的「无有效关联」正好相反,所以自然查不到正确结果。
下面给你两种最直观的正确写法,都能完美匹配你的需求:
方法一:用NOT EXISTS(逻辑最清晰,推荐)
这种写法直接对应需求的“不存在有效关联”的语义,非常容易理解:
SELECT s.id FROM s WHERE NOT EXISTS ( -- 子查询:检查当前s是否存在「活跃cs关联到活跃c」的记录 SELECT 1 FROM cs INNER JOIN c ON cs.c_id = c.id WHERE cs.s_id = s.id AND cs.del = 0 -- 只看活跃的中间表记录 AND c.del = 0 -- 只看活跃的c记录 )
逻辑验证(对应你的例子):
- s.id=1:子查询能找到
cs.s_id=1, cs.c_id=$, c.del=0这条符合条件的记录,所以NOT EXISTS不成立,不会被选中 - s.id=2:子查询找不到任何cs记录,
NOT EXISTS成立,会被选中 - s.id=3:所有活跃cs对应的c都是已删除的(c.del=1),子查询找不到符合条件的记录,
NOT EXISTS成立,会被选中
方法二:用LEFT JOIN + GROUP BY
如果你更习惯用连接的方式写,也可以用左连接筛选活跃关系,再通过分组计数判断:
SELECT s.id FROM s -- 左连接「活跃的cs记录」 LEFT JOIN cs ON s.id = cs.s_id AND cs.del = 0 -- 再左连接「活跃的c记录」(只关联和活跃cs匹配的c) LEFT JOIN c ON cs.c_id = c.id AND c.del = 0 GROUP BY s.id -- 分组后,如果活跃c的计数为0,说明没有有效关联 HAVING COUNT(c.id) = 0
逻辑验证:
- s.id=1:会关联到一条活跃cs+活跃c的记录,
COUNT(c.id)=1,不满足=0,不会被选中 - s.id=2:没有任何cs关联,
c.id全为null,COUNT(c.id)=0,会被选中 - s.id=3:活跃cs对应的c都是已删除的,所以左连接c后
c.id全为null,COUNT(c.id)=0,会被选中
为什么你的原查询不行?
再回头看你的SQL:
SELECT s.id FROM s LEFT JOIN cs on s.id = cs.s_id LEFT JOIN c on c.id = cs.c_id WHERE (cs.del = 0 OR cs.del IS NULL) AND (c.del = 0 OR c.del IS NULL) GROUP BY s.id HAVING COUNT(s.id) > 0
这里的问题:
- WHERE条件逻辑错误:你筛选的是「活跃cs/无cs」且「活跃c/无c」的记录,这其实是在找有有效关联的s,和需求完全相反
- HAVING条件错误:
COUNT(s.id)永远不会为0(因为s是主表,每条s至少有一条记录),这个条件完全起不到筛选作用
用上面推荐的两种写法,就能完美解决你的问题啦!
内容来源于stack exchange
相关产品推荐
相关产品推荐

