【问题标题】:Please explain differences between 2 SQL statements请解释2条SQL语句之间的区别
【发布时间】:2019-08-06 13:39:48
【问题描述】:

我已经写了 2 条 SQL 语句。

SELECT 
customers.CustomerID,
orders.OrderID
FROM customers LEFT JOIN orders ON customers.CustomerID = 
orders.CustomerID AND orders.EmployeeID=4
WHERE orders.OrderID IS NULL;

还有

SELECT 
customers.CustomerID,
orders.OrderID
FROM customers LEFT JOIN orders ON customers.CustomerID = 
orders.CustomerID AND orders.EmployeeID=4 AND orders.OrderID IS NULL;

第一个返回 16 个条目,这是正确的(根据解决方案)。第二个返回 91 个条目。我正在使用 Northwind 的 mysql 版本。我从某处读到,在 JOIN 语句中放置条件等同于在 WHERE 语句中放置条件。但是,在这里我可以看到不同之处。

【问题讨论】:

  • 参见dba.stackexchange.com/questions/196030/… "当你有一个 TableA a LEFT JOIN TableB b 场景时,你必须小心你如何在 WHERE 子句中使用 TableB 字段。对于 TableA 中没有的任何行匹配表 B 中的行,表 B 中的所有字段都将设置为 NULL。"
  • 不知道可以这样。但是,我仍然会将条件放在 WHERE 中,这样对我来说更容易阅读。我也对答案感兴趣。 @DotNetDev您可以考虑创建一个答案并使用链接作为备份源进行解释。不要在 cmets 中回答。
  • this question 的答案可能会有所帮助。
  • 第二个会产生更多的行。

标签: mysql sql


【解决方案1】:

这与语句的订单执行以及您使用LEFT JOIN这一事实有关。

LEFT JOIN 将保持左侧的所有值不变,仅组合右侧匹配条件的值。

WHERE 子句作为一个整体(在本例中)对查询进行操作。

查询 1:

  1. 从左表中获取所有值
  2. 加入右表中符合条件的任何值
  3. 根据 where 条件过滤连接的输出

查询 2:

  1. 从左表中获取所有值
  2. 加入右表中符合条件的任何值

WHERE 真正类似于JOIN 的唯一一次是类似于INNER JOIN,它只从左侧和右侧获取相关值。我想至少,我已经有一段时间没有锻炼 SQL 肌肉了。

编辑 - 计算 customers 表中的行数(仅此而已),它也应该返回 91。

【讨论】:

  • 是真的,返回91行。
  • @hacaoideas 计算表行数、不同列数等是 SQL 中非常有用的调试工具 :) 在对表运行任何查询之前,我会尝试找出有关表的一些一般信息。
  • 我有一个疑问。加入条件为ON ((customers.CustomerID = orders.CustomerID) AND (orders.EmployeeID=4) AND (orders.OrderID IS NULL)) 为什么只有满足这3个条件才加入?
  • @hacaoideas 它仅在满足条件时才运行。它只会从右表中检索与这些条件匹配的行,然后将它们连接到左边。因为它是LEFT JOIN,所以左表不会被修改。尝试运行RIGHTINNEROUTER 加入,看看结果如何变化。
  • 我只查看了查询 2 的完整返回集(select * from ...),我看到 EmployeeID 的所有值都是 NULL,而不是条件中指定的 4。
【解决方案2】:

第二个查询将返回更多行。为什么?继续阅读:

第二次查询

第二个查询将使用谓词将orders 行匹配到customers 行:

customers.CustomerID = orders.CustomerID AND orders.EmployeeID=4 AND orders.OrderID 为空

不匹配的customers 行将始终显示在结果中。

第一次查询

现在,第一个查询将使用谓词将 orders 行匹配到 customers 行:

customers.CustomerID = orders.CustomerID AND orders.EmployeeID=4

然后它将过滤掉orders.OrderID 为空的行,删除没有满足最后一个谓词的customer 行,因此产生更少的行。不匹配的客户行可能不会显示在结果中。

例子:

create table customers (
  CustomerId int
);

create table orders (
  OrderId int,
  CustomerId int,
  EmployeeId int
);

insert into customers (CustomerId) values (1), (2), (3);

insert into orders (OrderId, CustomerId, EmployeeId) values
  (1001, 1, 3),
  (1002, 1, 4),
  (1003, 2, 1);

第一个查询返回:

CustomerId  OrderId      
----------  ----------------
2           <null>       
3           <null>      

当第二个查询返回时:

CustomerId  OrderId      
----------  ----------------
1           <null>       
2           <null>       
3           <null>       

【讨论】:

    【解决方案3】:

    这可能是因为 Sql 查询的运行顺序 FROM 和 JOIN 。 FROM 子句和随后的 JOIN 将首先执行 WHERE 和最后选择。

    在第二种情况下,所有连接条件一起运行,但在第一种情况下,where 子句在连接数据和过滤后产生差异,而不是同时过滤,而是在连接后作为一个整体。

    【讨论】:

      猜你喜欢
      • 2021-03-11
      • 1970-01-01
      • 1970-01-01
      • 2018-06-27
      • 1970-01-01
      • 2015-06-04
      • 2011-06-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多