带关联表条件的左外连接:如何查询从未发布Cats主题帖子的用户
问题分析
你的查询之所以返回空集,核心原因是WHERE子句里的两个条件完全矛盾:
posts.user_id IS NULL筛选的是那些没有任何帖子的用户(LEFT JOIN后posts表的所有字段都会是NULL)- 同时又要求
posts.topic LIKE 'Cats',但当posts.user_id为NULL时,posts.topic必然也是NULL,不可能匹配到'Cats',这两个条件永远不可能同时满足,自然返回空集。
正确的解决方案
下面提供几种靠谱的写法,都能精准实现“查询所有从未发布过主题为‘Cats’的帖子的用户”的需求:
方案1:使用NOT EXISTS(推荐,性能最优)
这种写法逻辑最直观,直接找出“不存在对应‘Cats’主题帖子”的用户:
SELECT users.* FROM users WHERE NOT EXISTS ( SELECT 1 FROM posts WHERE posts.user_id = users.id AND posts.topic = 'Cats' -- 精确匹配用=即可,需要模糊匹配再换成LIKE '%Cats%' );
大多数数据库对这种关联子查询的优化做得很好,执行效率高,而且逻辑清晰不易出错。
方案2:LEFT JOIN + 筛选NULL
把对帖子主题的判断放到JOIN的ON条件里,这样LEFT JOIN后,那些没发过“Cats”帖子的用户(包括完全没发过帖子的用户)对应的posts记录会是NULL,再筛选这些NULL即可:
SELECT users.* FROM users LEFT JOIN posts ON users.id = posts.user_id AND posts.topic = 'Cats' WHERE posts.id IS NULL;
这里判断posts.id IS NULL比posts.user_id IS NULL更准确,因为id作为主键肯定不会是NULL,避免了user_id字段可能存在NULL的潜在问题。
方案3:使用NOT IN(需避坑)
如果用NOT IN,一定要注意排除posts表中user_id为NULL的记录,否则NOT IN会直接返回空集:
SELECT users.* FROM users WHERE users.id NOT IN ( SELECT posts.user_id FROM posts WHERE posts.topic = 'Cats' AND posts.user_id IS NOT NULL -- 必须加这个条件,规避NULL导致的逻辑错误 );
补充说明
如果你的需求是模糊匹配(比如主题包含“Cats”关键词),再把=换成LIKE '%Cats%',否则直接用=的查询效率更高。
内容的提问来源于stack exchange,提问作者User314159
相关产品推荐
相关产品推荐

