admin

使用LEFT JOIN(MySQL)时如何排除行

sql

我的 用户 有很多 帖子
。我想构建一个SQL查询,该查询将在1个查询(无子查询)中执行以下操作,并希望在可能的情况下不存在任何并集。我知道我可以用union来做到这一点,但我想了解是否可以仅使用联接来做到这一点。

我想获得以下不同活跃用户的列表:

  1. 没有帖子
  2. 没有批准的帖子

这是我到目前为止的内容:

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个,该职位已获批准。


阅读 330

收藏
2021-06-07

共1个答案

admin

考虑到您的需求并将其从字面上转换为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 。

但是,在我看来,这可以简化,因为 任何没有批准帖子的用户也将没有帖子 ,因此不需要合并条件。

在这种情况下,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;

这也将返回相同的两个用户。我想念什么吗?

2021-06-07