MySQL left join: null 元素被 where 过滤

MySQL left join: null elements be filtered by where

我有 2 个 MySQL table:join_test_ljoin_test_r

join_test_l:

+------+------+
| ca   | cb   |
+------+------+
| a    | s    |
| b    | s    |
| c    | d    |
| d    | NULL |
+------+------+

join_test_r:

+------+------+
| cc   | cb   |
+------+------+
| a    | NULL |
| b    | s    |
| c    | d    |
| d    | NULL |
+------+------+

当我尝试使用左连接和左侧 <> 过滤器进行查询时 table:

select * from join_test_l as l left join join_test_r as r on l.cb=r.cb where l.ca<>'c';
+------+------+------+------+
| ca   | cb   | cc   | cb   |
+------+------+------+------+
| a    | s    | b    | s    |
| b    | s    | b    | s    |
| d    | NULL | NULL | NULL |
+------+------+------+------+

l.canull 的行保留了下来。 当我尝试使用左连接和右侧的 <> 过滤器进行查询时 table:

select * from join_test_l as l left join join_test_r as r on l.cb=r.cb where r.cc<>'c';
+------+------+------+------+
| ca   | cb   | cc   | cb   |
+------+------+------+------+
| a    | s    | b    | s    |
| b    | s    | b    | s    |
+------+------+------+------+

r.ccnull 的所有行也被删除。

能解释一下吗? 我的意思是为什么结果集中的空值被 <> 子句过滤?

您需要将 WHERE 子句中的逻辑移动到 ON 子句中:

SELECT *
FROM join_test_l as l
LEFT JOIN join_test_r as r
    ON l.cb = r.cb AND r.cc <> 'c';

这里的问题是 WHERE 正在从结果集中过滤掉记录。另一方面,通过将逻辑移动到连接,我们保留了左侧 table join_test_l 中的每条记录。然后,对于 join_test_r.

中的每一列,未加入任何内容的记录将具有 null

重新 <> & null

x<>yx 不等于(通常意义上的)y and x is not null and y is not nulltrue。当 x 等于(在正常意义上)等于 y and x is not null and y is not null 时,它是 false。否则它在技术上是 unknown,但碰巧被 operators/syntax 当作 null 对待,就像 is.

大多数 SQL 运算符都是这样的——当每个参数 is not nullunknown(像 null 一样处理)时,它们 return 它们的正常结果除此以外。 SQL 运算符不是同名的普通关系运算符或数学运算符;他们特别对待(值)unknown & null。 (说 null 不是一个值是模糊无益的 SQL 文化修辞。)

Re "the "正常意义上的相等",来自MySQL 8.0参考手册 12.3.2 比较函数和运算符:

Comparison operations result in a value of 1 (TRUE), 0 (FALSE), or NULL.

  • <=>

    NULL-safe equal. This operator performs an equality comparison like the = operator, but returns 1 rather than NULL if both operands are NULL, and 0 rather than NULL if one operand is NULL. The <=> operator is equivalent to the standard SQL IS NOT DISTINCT FROM operator.

注意条件计算结果为 trueon & where return 行。当约束未评估为 false.

时,约束得到满足

Re left join on & where

了解什么 LEFT/RIGHT JOIN returns:INNER JOIN 行加上不匹配的 left/right table 行由 NULL 扩展。 FULL JOIN returns INNER JOIN rows UNION ALL unmatched left & right table rows extended by NULLs.始终知道您想要什么 INNER JOIN 作为 OUTER JOIN 的一部分。在 OUTER JOIN ON 删除任何由 NULL 扩展的行后,要求可能由 NULL 扩展的列不为 NULL 的 WHERE 或 ON,即仅留下 INNER JOIN 行,即 "turns an OUTER JOIN into an INNER JOIN"。你有那个。

阅读您的 SQL DBMS 文档。