SQL多表查询需求:获取无‘new’状态任务且含‘done’状态任务的用户ID列表
解决方案:筛选无'new'任务但有'done'任务的用户ID
嗨,针对这个需求,我给你提供两种常用的SQL实现方案,逻辑清晰且适配大多数主流数据库(比如MySQL、PostgreSQL、SQL Server等):
方案一:使用EXISTS和NOT EXISTS子查询(逻辑直观)
这种写法的优势是逻辑非常直白,很容易理解每一步的筛选条件:
SELECT DISTINCT t.user_id FROM tasks t WHERE EXISTS ( -- 确保该用户存在至少一个'done'状态的任务 SELECT 1 FROM tasks t_done WHERE t_done.user_id = t.user_id AND t_done.status = 'done' ) AND NOT EXISTS ( -- 确保该用户没有任何'new'状态的任务 SELECT 1 FROM tasks t_new WHERE t_new.user_id = t.user_id AND t_new.status = 'new' );
这里的DISTINCT是为了避免同一个用户ID因为多条'done'任务而重复出现在结果里,如果你确定每个符合条件的用户只会被匹配一次,也可以去掉,但加上更稳妥。
方案二:使用GROUP BY + HAVING聚合筛选(简洁高效)
如果偏好聚合统计的写法,可以用分组后筛选的方式,代码更简洁:
SELECT user_id FROM tasks GROUP BY user_id HAVING -- 统计该用户的'new'任务数量为0 SUM(CASE WHEN status = 'new' THEN 1 ELSE 0 END) = 0 -- 统计该用户的'done'任务数量至少为1 AND SUM(CASE WHEN status = 'done' THEN 1 ELSE 0 END) > 0;
也可以用COUNT替代SUM,效果是一样的(因为COUNT会忽略NULL值):
SELECT user_id FROM tasks GROUP BY user_id HAVING COUNT(CASE WHEN status = 'new' THEN 1 END) = 0 AND COUNT(CASE WHEN status = 'done' THEN 1 END) > 0;
验证结果
根据你提供的示例数据,这两个方案都会返回user_id = 2,完全符合需求:
- 用户2没有任何'new'任务,且存在多个'done'任务;
- 用户1、4有'new'任务,用户3只有'new'任务,都会被排除。
内容的提问来源于stack exchange,提问作者mrlethal
相关产品推荐
相关产品推荐

