数据库管理工具Navicat使用教程:介绍常见的SQL 查询错误(一)

外部联接(Outer Join)和笛卡尔积(Cartesian Product)

在这个关于“常见的 SQL 查询错误”的系列中,我们一直在探索看似直观的 SQL 查询构造方法如何导致反模式,从而导致错误结果和/或性能降低。上周,我们暂停了这个系列,讨论了 SQL 中的谓词。在本期文竟中,我们将学习它们的位置如何对查询执行产生负面影响,尤其是在外部联接中。

什么是外部联接/strong>

在链接相关的表和视图时,可使用四种基本的联接类型:内部联接、左联接、右联接和外部联接。内部联接不会返回任何一个表中在另一个表中不匹配的行。外部联接可以返回一个或两个表中不匹配的行。而最后三种连接类型都是外部联接的一种,其中:

  • LEFT JOIN 仅返回左表中不匹配的行。
  • RIGHT JOIN 仅返回右表中不匹配的行。
  • FULL OUTER JOIN 返回两个表中不匹配的行。
外部联接如何出错

虽然外部联接在数据库从业者中肯定占有一席之地,但即使在不需要它们的情况下,开发人员也倾向于使用它们。此外,外部联接查询可能会产生完全不同的结果,具体取决于你构建它的方式以及你在查询中放置谓词的位置。为了说明这一点,让我们看看一个示例。

我们想检索所有客户的列表(无论他们是否下过任何订单),以及自 2005 年 6 月开始以来他们下的订单总数。为此,我们将使用外部联接来链接 customers 和 orders 表,如下所示:

SELECT C.customerName, count(O.customerNumber) AS 2005_ordersFROM customers AS CLEFT OUTER JOIN orders AS O  ON C.customerNumber = O.customerNumberWHERE O.orderDate >= '2005-05-01'GROUP BY C.customerNameORDER BY 2005_orders DESC;

查询结果应包含第一个表和第二个表中所有可能的行组合,也称为笛卡尔积。不幸的是,当我们在 Navicat Premium 16 中运行查询时,仅返回 13 行,尽管表中有 122 个客户(未显示):

数据库管理工具 Navicat Premium 16

为了理解哪里出了问题,让我们一步一步从列和外部联接开始重建查询:

数据库管理工具 Navicat Premium 16

现在我们得到了所有的客户。那些没有下任何订单的客户的 customerNumbers 为 NULL,因为它们来自 orders 表。

现在,让我们应用 WHERE 子句谓词:

数据库管理工具 Navicat Premium 16

问题是 WHERE 子句中的谓词将外部联接变成了内部联接。为了纠正这个问题,我们需要将 WHERE 谓词添加到联接条件:

数据库管理工具 Navicat Premium 16

我们现在可以调整原本的查询以获取所有客户:

数据库管理工具 Navicat Premium 16

谨记要时刻注意筛选掉的行的位置。在上述示例中,WHERE 子句是问题所在。在一个更复杂的示例中,如果有多个联接,错误的筛选可能发生在后续表运算符(如联接到另一个表)而不是 WHERE 子句中。

更多有关Navicat Premium使用教程可点击查看,欢迎加入Navicat Premium技术交流QQ群:765665608

Navicat Premium | 下载试用

Navicat Premium 是一套数据库管理工具,让你使用一个程序即可同時连接到 MySQL、MariaDB、SQL Server、SQLite、Oracle 和 PostgreSQL 数据库。了解更多购买详情可联系在线客服。

标签:

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年5月7日
下一篇 2022年5月7日

相关推荐

发表回复

登录后才能评论