警惕“左”连接 - 左连接本质上是外连接。不同的 RDBMS 查询解析器和优化器可能会非常不同地处理 OUTER JOINS。以 MySQL 的查询优化器如何解析 LEFT (OUTER) JOINS 为例,以及它们可以评估每次迭代的结果执行计划的差异:
https://dev.mysql.com/doc/refman/8.0/en/outer-join-simplification.html
LEFT JOINS 就其本质而言始终是非确定性的。IMO - 它们不应在生产代码中使用。
我更喜欢首先以更“老派”的方法编写 JOIN 类型语句,而忽略任何特定的 JOIN 声明。让 RDBMS 查询解析器完成其设计的工作 - 分析您的语句并根据对索引统计和数据模型设计的评估将其转换为最佳执行计划。也就是说,查询解析器/优化器的构建甚至会出错,相信我,我已经看到它发生过很多次了。总的来说,我觉得首先采用这种方法通常会提供足够的基线信息,以便在大多数情况下做出明智的进一步调整决策。
为了说明 - 使用此线程中的问题查询:
SELECT `voter`.`ID`, `voter`.`Last_Name`, `voter`.`First_Name`,
`voter`.`Middle_Name`, `voter`.`Age`, `voter`.`Sex`,
`voter`.`Party`, `voter`.`Demo`, `voter`.`PV`,
`household`.`Address`, `household`.`City`, `household`.`Zip`
FROM (`voter`)
JOIN `household` ON `voter`.`House_ID`=`household`.`id`
WHERE `CT` = '5'
AND `Precnum` = 'CTY3'
AND `Last_Name` LIKE '%Cumbee%'
AND `First_Name` LIKE '%John%'
AND NOT EXISTS (
SELECT * FROM `elimination`
WHERE `elimination`.`voter_id` = `voter`.`ID`
)
ORDER BY `Last_Name` ASC
LIMIT 30
考虑在没有上述显式 JOIN 和 NOT EXISTS 语句的情况下重写它(假设 WHERE 子句中的非完全限定字段属于选民表):
SELECT v.`ID`, v.`Last_Name`, v.`First_Name`,
v.`Middle_Name`, v.`Age`, v.`Sex`,
v.`Party`, v.`Demo`, v.`PV`,
h.`Address`, h.`City`, h.`Zip`
FROM `voter` v, `household` h, `elimination` e
WHERE v.`House_ID` = h.`id`
AND v.`ID` != e.`voter_id`
AND v.`CT` = '5'
AND v.`Precnum` = 'CTY3'
AND v.`Last_Name` LIKE '%Cumbee%'
AND v.`First_Name` LIKE '%John%'
ORDER BY v.`Last_Name` ASC
LIMIT 30;
尝试在语法上以两种方式编写一些未来的 SQL 查询,比较它们的结果,看看你的想法。以我上面建议的风格编写 SQL 还带来了更多与 RDBMS 无关的额外好处。
干杯!