左连接行为问题:使用 WHERE 子句转换为内连接
考虑以下 SQL 语句:
SELECT a.foo b.bar c.foobar FROM tableOne AS a INNER JOIN tableTwo AS b ON a.pk = b.fk LEFT JOIN tableThree AS c ON b.pk = c.fk WHERE a.foo = 'something' AND c.foobar = 'somethingelse'
在这种情况下,期望的是左连接行为。然而,观察到的行为是,左连接似乎根据 AND c.foobar = 'somethingelse' 子句的存在而转换为内连接。 tableThree 中缺少相应 'somethingelse' 值的行不会被返回。
理解行为
关键点在于 WHERE 子句和 LEFT JOIN 之间的交互。当在 WHERE 子句中从左联接的右侧指定非 NULL 值时,NULL 值将被消除,从而有效地将联接转变为内联接。
在这种情况下,AND c. foobar = 'somethingelse' 子句过滤掉 tableThree 中 foobar 为 NULL 的行。这意味着仅返回 tableTwo 和 tableThree 中具有匹配非 NULL 值的行。
解决方案
要解决此行为并恢复预期的左连接,有有两个选项:
AND (c.foobar = 'somethingelse' OR c.foobar IS NULL)
此添加允许包含 tableThree 中的 NULL 值,保留左连接行为。
LEFT JOIN tableThree AS c ON b.pk = c.fk AND c.foobar = 'somethingelse'
通过移动c.foobar条件放入连接谓词中,查询显式指定连接内所需的过滤条件,确保仅连接匹配的行。
以上是为什么在 WHERE 子句中过滤右侧列时,LEFT JOIN 会变成 INNER JOIN?的详细内容。更多信息请关注PHP中文网其他相关文章!