最常见的 SQL 查询错误 - 第三章节
外部联接(Outer Join)和笛卡尔积(Cartesian Product)
在这个关于“常见的 SQL 查询错误”的系列中,我们一直在探索看似直观的 SQL 查询构造方法如何导致反模式,从而导致错误结果和/或性能降低。上周,我们暂停了这个系列,讨论了 SQL 中的谓词。在本期文竟中,我们将学习它们的位置如何对查询执行产生负面影响,尤其是在外部联接中。
什么是外部联接?
在链接相关的表和视图时,可使用四种基本的联接类型:内部联接、左联接、右联接和外部联接。内部联接不会返回任何一个表中在另一个表中不匹配的行。外部联接可以返回一个或两个表中不匹配的行。而最后三种连接类型都是外部联接的一种,其中:
- LEFT JOIN 仅返回左表中不匹配的行。
- RIGHT JOIN 仅返回右表中不匹配的行。
- FULL OUTER JOIN 返回两个表中不匹配的行。
外部联接如何出错
虽然外部联接在数据库从业者中肯定占有一席之地,但即使在不需要它们的情况下,开发人员也倾向于使用它们。此外,外部联接查询可能会产生完全不同的结果,具体取决于你构建它的方式以及你在查询中放置谓词的位置。为了说明这一点,让我们看看一个示例。
我们想检索所有客户的列表(无论他们是否下过任何订单),以及自 2005 年 6 月开始以来他们下的订单总数。为此,我们将使用外部联接来链接 customers 和 orders 表,如下所示:
SELECT C.customerName, count(O.customerNumber) AS 2005_orders
FROM customers AS C
LEFT OUTER JOIN orders AS O
ON C.customerNumber = O.customerNumber
WHERE O.orderDate >= '2005-05-01'
GROUP BY C.customerName
ORDER BY 2005_orders DESC;
查询结果应包含第一个表和第二个表中所有可能的行组合,也称为笛卡尔积。不幸的是,当我们在 Navicat Premium 16 中运行查询时,仅返回 13 行,尽管表中有 122 个客户(未显示):
为了理解哪里出了问题,让我们一步一步从列和外部联接开始重建查询:
现在我们得到了所有的客户。那些没有下任何订单的客户的 customerNumbers 为 NULL,因为它们来自 orders 表。
现在,让我们应用 WHERE 子句谓词:
突然之间,很多客户消失了!问题是 WHERE 子句中的谓词将外部联接变成了内部联接。
为了纠正这个问题,我们需要将 WHERE 谓词添加到联接条件:
我们现在可以调整原本的查询以获取所有客户:
故事的重点
谨记要时刻注意筛选掉的行的位置。在上述示例中,WHERE 子句是问题所在。在一个更复杂的示例中,如果有多个联接,错误的筛选可能发生在后续表运算符(如联接到另一个表)而不是 WHERE 子句中。
如果你想试用最新的 Navicat 16 for MySQL,你可以在这里下载免费的 14 天全功能试用版。
相关文章
- SQL Server 中 EXEC全称execute 与 SP_EXECUTESQL动态执行sql代码语句 的区别
- SQL案例分析-地铁换乘线路查询.sql
- 最常见的 SQL 查询错误 - 第一章节
- 【Python】读写文件时 编码错误 https://www.cnblogs.com/baijing1/p/9885891.html
- Redis 错误1067:进程意外终止,Redis不能启动,Redis启动不了
- sql语言实践之自学SQL网(SQL Lesson12)
- sql语言实践之自学SQL网(SQL Lesson10,11)
- springData Jpa 错误:java.sql.SQLSyntaxErrorException: Table 'a2.hibernate_sequence' doesn't exist
- 转 EXPDP ORA-39095 ORA-3909 错误
- 实战案例:Sql client使用sql操作FlinkCDC2Hudi、支持从savepoint恢复hudi作业
- SQL Server: Get table primary key and Foreign Key using sql query
- sql: MySQL and Microsoft SQL Server Stored Procedures IN, OUT using csharp code
- MySQL创建方法错误:This function has none of DETERMINISTIC, NO SQL
- SQL Server数据库状态监控 - 错误日志
- Git 常见错误 之 fatal: remote error: CAPTCHA required 简单解决方法
- 怎样使用oracle 的DBMS_SQLTUNE package 来执行 Sql Tuning Advisor 进行sql 自己主动调优
- sql server启动报错 TDSSNIClient 初始化失败,出现错误 0xffffffff,状态代码 0x80。原因: Unable to initialize SSL support.
- sql server该账户当前被锁定,所以用户'sa'登录失败。系统管理员无法将该账户解锁。(Microsoft SQL Server,错误:18486),登录错误18456
- MariaDB新增数据报错:SQL 错误 [1366] [22007]: (cIncorrect string value: ‘xE5xBCxA0xE4xB8x89‘ for column