我有2个MySQL表:join_test_l
和join_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 |
+------+------+
,当我尝试使用左侧联接和左侧表上的<>
过滤器进行查询时:
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.ca
为null
的行。
当我尝试使用左联接和右表上的<>
过滤器进行查询时:
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.cc
为null
的所有行也被删除。
能解释一下吗?
我的意思是为什么结果集中的空值被<>
子句过滤?
答案 0 :(得分:2)
关于<>
和null
x<>y
与true
x
不相等时(通常意义上), y
为and x is not null and y is not null
。当false
等于(在正常意义上)等于x
y
时为and x is not null and y is not null
。否则,从技术上讲,它是unknown
,但是碰巧像null
这样的运算符/语法将其视为is
。
大多数SQL运算符都是这样的-当每个参数is not null
和其他参数unknown
(与null
一样对待时,它们返回其正常结果。
SQL运算符不是具有相同名称的普通关系或数学运算符;他们特别对待unknown
和null
(值)。 (说null
不是一个值是模糊无助的SQL文化言论。)
来自the MySQL 8.0 Reference Manual 12.3.2 Comparison Functions and Operators的“正常的平等感”:
比较操作得出的值为
1
(TRUE
),0
(FALSE
)或NULL
。
<=>
NULL
-相等。该运算符执行类似于=
运算符的相等比较,但是如果两个操作数均为1
,则返回NULL
而不是NULL
,如果返回两个,则返回0
而不是NULL操作数为NULL
。<=>
运算符等效于标准SQLIS NOT DISTINCT FROM
运算符。
注释on
和where
返回条件评估为true
的行。当约束的评估结果不为false
时,这些约束就会满足。
关于left join
on
和where
了解LEFT / RIGHT JOIN返回的内容:INNER JOIN行以及不匹配的左/右表行,这些行由NULL扩展。 FULL JOIN返回INNER JOIN行UNION ALL,所有不匹配的左右表行扩展为NULL。始终知道您要作为OUTER JOIN的一部分的INNER JOIN。在WHERE或ON上,在OUTER JOIN ON上需要一个可能为NULL扩展的列不为NULL的情况下,删除所有扩展为NULL的行,即仅保留INNER JOIN行,即“将OUTER JOIN转换为INNER JOIN”。你有那个。
阅读您的SQL DBMS文档。
答案 1 :(得分:1)
您需要将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
正在从结果集中过滤掉记录。另一方面,通过将逻辑移到联接,我们将每个记录保留在左表join_test_l
中。然后,未连接任何记录的记录在null
中的每一列中将有join_test_r
。