如何简化查询仅发布过类型1和2帖子的用户列表的SQL语句?
优化方案:获取仅发布类型1和2帖子的用户列表
你的原始SQL逻辑正确,但可以通过分组聚合等方式简化写法,以下是几种更简洁高效的实现方案:
方法1:分组后用HAVING多条件过滤
通过分组统计用户的帖子类型分布,一步完成所有筛选逻辑:
SELECT user_id FROM post GROUP BY user_id HAVING -- 确保用户至少发布过1条类型1的帖子 SUM(CASE WHEN type_id = 1 THEN 1 ELSE 0 END) > 0 -- 确保用户至少发布过1条类型2的帖子 AND SUM(CASE WHEN type_id = 2 THEN 1 ELSE 0 END) > 0 -- 确保用户没有发布过1、2之外的其他类型帖子 AND SUM(CASE WHEN type_id NOT IN (1,2) THEN 1 ELSE 0 END) = 0;
如果你的数据库支持布尔值转整数(如MySQL),可以进一步简化统计部分:
SELECT user_id FROM post GROUP BY user_id HAVING SUM(type_id = 1) > 0 AND SUM(type_id = 2) > 0 AND SUM(type_id NOT IN (1,2)) = 0;
方法2:利用去重计数+极值判断
如果用户仅发布过1和2类型的帖子,那么其所有帖子的去重类型数必为2,且类型的最小、最大值恰好是1和2:
SELECT user_id FROM post GROUP BY user_id HAVING COUNT(DISTINCT type_id) = 2 AND MIN(type_id) = 1 AND MAX(type_id) = 2;
注:该写法仅适用于不存在小于1或大于2的其他类型的场景,完全匹配你的需求。
方法3:简化EXISTS子查询写法
若偏好保留EXISTS的查询风格,可以合并前两个子查询,减少表扫描次数:
SELECT DISTINCT user_id FROM post p1 WHERE EXISTS ( SELECT 1 FROM post p2 WHERE p2.user_id = p1.user_id AND p2.type_id IN (1,2) GROUP BY p2.user_id HAVING COUNT(DISTINCT p2.type_id) = 2 ) AND NOT EXISTS ( SELECT 1 FROM post p2 WHERE p2.user_id = p1.user_id AND p2.type_id NOT IN (1,2) );
性能优化建议
为post表创建user_id和type_id的联合索引:
CREATE INDEX idx_post_user_type ON post(user_id, type_id);
该索引能大幅提升所有方案的查询效率,让数据库直接通过索引完成统计和筛选,无需扫描全表。
内容的提问来源于stack exchange,提问作者dafie
相关产品推荐
相关产品推荐

