我的 用户 有很多 帖子 。我想构建一个SQL查询,该查询将在1个查询(无子查询)中执行以下操作,并希望在可能的情况下不存在任何并集。我知道我可以用union来做到这一点,但我想了解是否可以仅使用联接来做到这一点。
我想获得以下不同活跃用户的列表:
这是我到目前为止的内容:
SELECT DISTINCT u.* FROM users u LEFT JOIN posts p ON p.user_id = u.id LEFT JOIN posts p2 ON p2.user_id = u.id WHERE u.status = 'active' AND (p.status IS NULL OR p2.status != 'approved');
问题是当用户有多个帖子并且一个帖子处于活动状态时。这仍然会返回我不想要的用户。如果用户有活跃帖子,则应将其从结果集中删除。有任何想法吗?
数据如下所示:
mysql> select * from users; +----+---------+ | id | status | +----+---------+ | 1 | active | | 2 | pending | | 3 | pending | | 4 | active | | 5 | active | +----+---------+ 5 rows in set (0.00 sec) mysql> select * from posts; +----+---------+----------+ | id | user_id | status | +----+---------+----------+ | 1 | 1 | approved | | 2 | 1 | pending | | 3 | 4 | pending | +----+---------+----------+ 3 rows in set (0.00 sec)
答案应该仅是用户4和5。4没有批准的帖子,而5没有帖子。它不应包含1个,该职位已获批准。
考虑到您的需求并将其从字面上转换为SQL,我得到以下信息:
SELECT users.id, COUNT(posts.id) as posts_count, COUNT(approved_posts.id) as approved_posts_count FROM users LEFT JOIN posts ON posts.user_id = users.id LEFT JOIN posts approved_posts ON approved_posts.status = 'approved' AND approved_posts.user_id = users.id WHERE users.status = "active" GROUP BY users.id HAVING (posts_count = 0 OR approved_posts_count = 0);
对于上面的测试数据,将返回:
4|1|0 5|0|0
即具有ID4和的用户5,其中第一个具有1个帖子,但没有批准的帖子,而第二个没有ID 。
4
5
但是,在我看来,这可以简化,因为 任何没有批准帖子的用户也将没有帖子 ,因此不需要合并条件。
在这种情况下,SQL就是:
SELECT users.id, COUNT(approved_posts.id) as approved_posts_count FROM users LEFT JOIN posts approved_posts ON approved_posts.status = 'approved' AND approved_posts.user_id = users.id WHERE users.status = "active" GROUP BY users.id HAVING approved_posts_count = 0;
这也将返回相同的两个用户。我想念什么吗?