【问题标题】:How to use joins in SQL [closed]如何在 SQL 中使用连接 [关闭]
【发布时间】:2020-05-11 23:20:12
【问题描述】:

这是我试图理解的一个问题:

假设一个网站包含两个表,Customers 表和 Orders 表。

编写一个 SQL 查询来查找所有从未订购过任何东西的客户。

表:客户。

+----+-------+
| Id | Name  |
+----+-------+
| 1  | Joe   |
| 2  | Henry |
| 3  | Sam   |
| 4  | Max   |
+----+-------+

表格:订单。

+----+------------+
| Id | CustomerId |
+----+------------+
| 1  | 3          |
| 2  | 1          |
+----+------------+

以上表为例,返回以下内容:

+-----------+
| Customers |
+-----------+
| Henry     |
| Max       |
+-----------+

解决方案:

SELECT Name AS Customers 
FROM Customers AS c LEFT JOIN Orders AS o ON c.Id = o.CustomerId
WHERE o.Id IS NULL;

有谁知道我们为什么使用 c.Id = o.CustomerId 来匹配列以及为什么我们选择 o.Id 为 Null 而不是其他列?

【问题讨论】:

  • 这听起来像是复制/粘贴学校作业......我不认为这就是 SO 的目的。
  • 听起来像是一个我们无法回答的意见问题。可以写成SELECT Name FROM Customers where id not in(select customerid from orders group by customerid) 和其他几种方式。
  • 我相信 OP 要求的是加入两列的逻辑,而不是其他示例......

标签: mysql sql database join left-join


【解决方案1】:

正如 Kevin 所提到的,CustomerId 是 Orders 表的外键。 left outer join 将两个表与具有连接条件中指定的匹配数据的行组合在一起,如果没有匹配数据,则为 null。这意味着left outer join 使用c.Id = o.CustomerId 将创建以下表格选择:

+------+--------+------+--------------+
| c.Id | c.Name | o.Id | o.CustomerId |
+------+--------+------+--------------+
|   1  | Joe    |  2   |     1        |
|   2  | Henry  | NULL |    NULL      |
|   3  | Sam    |  1   |     3        |
|   4  | Max    | NULL |    NULL      |
+----+----------+------+--------------+

如果我们使用上表中的 where 子句 WHERE o.Id IS NULL 进行选择,我们将收到 Id 为 2 和 4 的行,因为 o.Id 对于这些行是空的。

【讨论】:

  • 很好的解释
【解决方案2】:

原因是因为Orders表中的CustomerId列是Customers表中Id列的外键。因此,要正确连接这两个表,它就在这两列上。

在我看来,这些列的命名很糟糕,如果在两个表中都是 CustomerId,那就更有意义了。

【讨论】:

  • FK 和其他约束不需要查询。 FK 和其他约束是否成立与查询含义无关,只是添加约束会使某些表达式返回与查询相同的结果,无论约束是否成立。
【解决方案3】:

已经解释了现有查询的工​​作原理。

我发现not exists 是表达这个查询的更直接和易懂的方式:

select c.*
from customers c
where not exists (select 1 from orders o where o.customer_id = c.id)

使用orders(custmer_id) 上的索引,这实际上可能比反左连接解决方​​案执行得更好。

【讨论】:

    【解决方案4】:
    Does anyone know why we are using c.Id = o.CustomerId to match the columns?
    

    因为我们通过这些列生成 2 个表。我们可能会使用其他产品,产品可能会有所不同。

    Why we are choosing o.Id to be Null and not the other columns? 
    

    这是一个过滤器,您可以使用任何您需要的条件,结果集也可以不同。

    附:在大多数情况下,LEFT 加入过滤器的主键(但它变成 INNER JOIN 之后)

    【讨论】:

      猜你喜欢
      • 2017-06-18
      • 1970-01-01
      • 1970-01-01
      • 2016-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多