MySQL:left join 后用 on 照旧 where?

打印 上一主题 下一主题

主题 523|帖子 523|积分 1569

在MySQL中,LEFT JOIN用于返回左表(即LEFT JOIN关键字左边的表)的全部记录,即使在右表中没有匹配的记录。对于那些右表中没有匹配的记录,结果会合右表的部门会被添补为NULL。关于ON和WHERE子句的使用,它们在LEFT JOIN中的作用是不同的:


  • ON 子句:用于定义毗连条件,即决定哪些记录应该被毗连在一起。当你需要基于左右表的某些字段值的关系来组合记录时,这些条件应该放在ON后面。假如在ON后面还有对右表的额外条件限制,这些也会在毗连时应用,但不会影响左表返回全部记录的原则。
  • WHERE 子句:用于对已经通过JOIN操纵产生的结果集进行进一步的过滤。当条件放在WHERE子句中时,那些不符合条件的记录(无论是左表的照旧右表的)都会被移除,这可能会影响到左表返回全部记录的初志,尤其是在处理惩罚NULL值时需格外小心。
详细案例一:
假设我们有两个表,一个是employees(员工表),另一个是departments(部门表),我们想找出全部员工及其所在的部门名称,即使某些员工没有分配到详细的部门。
employees 表:
idname1Alice2Bob3Carol departments 表:
idname1HR2IT3Marketing 其中,employees表的department_id字段可以是NULL,表现没有分配部门。
使用 ON 示例:
  1. SELECT employees.name, departments.name AS department_name
  2. FROM employees
  3. LEFT JOIN departments ON employees.department_id = departments.id;
复制代码
这个查询会返回全部员工的名字,以及他们对应的部门名字,假如员工没有部门(即department_id为NULL),部门名字则为NULL。
使用 WHERE 示例:
  1. SELECT employees.name, departments.name AS department_name
  2. FROM employees
  3. LEFT JOIN departments ON employees.department_id = departments.id
  4. WHERE departments.id IS NOT NULL;
复制代码
这个查询试图过滤掉那些部门ID为NULL的记录,但由于使用的是LEFT JOIN,加上WHERE子句过滤掉NULL的部门ID实际上会导致那些没有分配部门的员工也被清除在外,违反了LEFT JOIN的初志,即返回左表全部记录。因此,在大多数情况下,假如你想保存左表的全部记录,应避免在WHERE子句中过滤与右表相关的NULL值,而是应该在ON子句中完成全部必要的毗连条件和限制。
准确的做法是在ON子句中处理惩罚全部毗连条件,然后仅在确实需要进一步过滤整个结果集(而不影响左表完整性)时才使用WHERE子句。
详细案例二:
假设我们有两个表,一个是Orders(订单表),一个是Customers(客户表),我们想找出全部客户的订单信息,即使某些客户还没有下过任何订单。
Orders表:


  • OrderID
  • CustomerID
  • ProductName
Customers表:


  • CustomerID
  • CustomerName
使用ON的例子
假如我们想找到全部客户的订单,即使他们没有订单,我们会这样写:
  1. SELECT Customers.CustomerName, Orders.ProductName
  2. FROM Customers
  3. LEFT JOIN Orders ON Customers.CustomerID = Orders.CustomerID;
复制代码
在这个查询中,ON子句确保了每个客户与他们的订单关联,即使没有订单的客户也会出现在结果会合,其ProductName为NULL。
使用WHERE的例子
假如我们进一步想在结果中只包括那些至少有一个订单的客户,我们可能会实验这样写,但这是错误的做法,由于它违反了LEFT JOIN的初志:
  1. SELECT Customers.CustomerName, Orders.ProductName
  2. FROM Customers
  3. LEFT JOIN Orders ON Customers.CustomerID = Orders.CustomerID
  4. WHERE Orders.OrderID IS NOT NULL; -- 这里会过滤掉左表中无匹配项的记录
复制代码
上述查询实际上会酿成内毗连的效果,由于WHERE子句清除了左表中没有匹配项(即订单为NULL)的记录。
准确的使用方式
假如我们的目的是在保存全部客户的同时,筛选出有订单的客户信息,我们应该这样写:
  1. SELECT Customers.CustomerName, Orders.ProductName
  2. FROM Customers
  3. LEFT JOIN Orders ON Customers.CustomerID = Orders.CustomerID AND Orders.OrderID IS NOT NULL;
复制代码
在这个修正的查询中,我们在ON子句中同时指定了毗连条件和筛选条件,这样既包管了左表的完整性,又对毗连后的结果进行了有效的过滤,只保存了那些有订单的记录。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

前进之路

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表