【问题标题】:SQL: How to find rows in one table that have no references to rows in another tables?SQL:如何在一个表中查找没有引用另一表中的行的行?
【发布时间】:2021-10-02 18:31:05
【问题描述】:

我有三个表:usersroomsroom_users。 用户可以有很多房间,房间也可以有很多用户,所以这是多对多的关系。

users表:

+----+-----------+-----+
| id |   name    | age |
+----+-----------+-----+
| 1  | Christian | 19  |
| 2  | Ben       | 36  |
| 3  | Robert    | 52  |
| 4  | Monica    | 25  |
| 5  | Alice     | 26  |
| 6  | William   | 18  |
+----+-----------+-----+

rooms表:

+----+----------+
| id |   name   |
+----+----------+
| 1  | College  |
| 2  | Work     |
| 3  | Football |
+----+----------+

还有代表用户和房间关系的room_users表:

+---------+---------+
| user_id | room_id |
+---------+---------+
| 1       | 1       |
| 1       | 3       |
| 2       | 2       |
| 4       | 1       |
| 5       | 2       |
| 6       | 1       |
| 6       | 3       |
+---------+---------+

所以,有了这些表,我们可以说:

  • Christian(1) 属于 College(1) 和 Football(3) 房间。
  • Ben(2) 属于 Work(2) 房间。
  • Robert(3) 不属于任何房间。
  • Monica(4) 属于 College(1) 房间。
  • Alice(5) 属于 Work(2) 房间。
  • William(1) 属于 College(1) 和 Football(3) 房间。

现在,如果我想找到属于 Football room 的用户 (id),我应该使用以下查询:

SELECT user_id FROM room_users WHERE room_id = 3

此查询的输出:

+---------+
| user_id |
+---------+
| 1       |
| 6       |
+---------+

这是正确的,只有 Christian(1) 和 William(3) 属于 Football room。

但是如何找到不属于足球室的用户呢? 在这种情况下,查询必须返回 2、3、4 和 5 个 ID。也就是说,除了第一个查询中的 ID 之外的所有 ID。

是否可以使用LEFT JOIN 来做到这一点? 据我所知,它比使用子查询更有效。

提前致谢!

编辑:

我找到了一个可以解决问题的查询,但是这个查询在大型数据库上非常慢:

SELECT users.id FROM users WHERE 0=(SELECT COUNT(*) FROM room_users WHERE user_id=users.id AND room_id=3);

【问题讨论】:

    标签: sql left-join relational-database


    【解决方案1】:

    如果没有相关行为,请尝试以下操作:

    SELECT u.*
      FROM users AS u
      LEFT JOIN (
              SELECT DISTINCT user_id FROM room_users WHERE room_id = 3
           ) AS v
        ON v.user_id = u.id
     WHERE v.user_id IS NULL
    ;
    

    对于性能问题,首先查看解释/执行计划和索引的使用。

    【讨论】:

      【解决方案2】:

      您可以找到属于足球室的用户,然后排除那些使用 not in 的用户。 您也可以使用 JOIN

      SELECT u.*
      FROM
      users u
      WHERE user_id NOT IN
      (SELECT user_id FROM room_users WHERE room_id=3)
      

      【讨论】:

      • 在这种情况下,不属于任何房间的用户(在我的示例中是 id 为 3 的 Robert)将不会包含在结果中。
      • 这个查询可以改进如下。 SELECT id FROM users WHERE id NOT IN (SELECT user_id FROM room_users WHERE room_id=3);
      【解决方案3】:

      你说得对,这可以通过左连接来实现。

      SELECT
          u.id
      FROM
          users u
      LEFT JOIN room_users ur
      ON u.id = ur.user_id
      AND ur.room_id = 3
      WHERE
          ur.room_id is null;
      

      【讨论】:

        猜你喜欢
        • 2010-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多