在MySQL 8系列版本中,有使用count等聚合函数的SQL。执行 LEFT JOIN,在 WHERE 子句中指定为“IS NULL”的模式的行为与在 ON 子句中指定为“IS NULL”的模式的行为不同。为什么?
-- pattern1
SELECT count(a.value)
FROM A AS a
LEFT JOIN B AS b
ON a.id = b.id
WHERE b.value IS NULL
;
-- pattern2
SELECT count(a.value)
FROM A AS a
LEFT JOIN B AS b
ON a.id = b.id
AND b.value IS NULL
;
-- pattern1's result = 3549
-- pattern2's result = 4000
一张表有4000条记录
当一个表的条件放在 WHERE 中时,它会在加入后应用。
当一个表的条件被置于 ON 时,它会在(但这看起来像之前)加入期间应用。
CREATE TABLE t1
SELECT 1 id, 1 val UNION ALL
SELECT 2, 2 UNION ALL
SELECT 3, 3;
CREATE TABLE t2
SELECT 1 id, 1 val UNION ALL
SELECT 2, 2 UNION ALL
SELECT 4, 4 UNION ALL
SELECT NULL, 5;
SELECT *
FROM t1
LEFT JOIN t2 ON t1.id = t2.id;
id | val | id | val |
---|---|---|---|
1 | 1 | 1 | 1 |
2 | 2 | 2 | 2 |
3 | 3 | 空 | 空 |
First SELECT 在没有附加条件的情况下连接表。
SELECT *
FROM t1
LEFT JOIN t2 ON t1.id = t2.id
WHERE t2.id IS NULL;
id | val | id | val |
---|---|---|---|
3 | 3 | 空 | 空 |
第二个 SELECT 包含 WHERE 中右表的附加条件。此条件在加入后应用,即应用于第一个 SELECT 返回的行集,并且只返回一行。
SELECT *
FROM t1
LEFT JOIN t2 ON t1.id = t2.id
AND t2.id IS NULL;
SELECT * FROM t2 WHERE t2.id IS NULL;
id | val | id | val |
---|---|---|---|
1 | 1 | 空 | 空 |
2 | 2 | 空 | 空 |
3 | 3 | 空 | 空 |
id | val |
---|---|
空 | 5 |
Third SELECT contains additional condition by right table in ON,应用于源表。这是另外显示的。
SELECT *
FROM t1
LEFT JOIN t2 ON t1.id = t2.id
WHERE t1.id > 1;
id | val | id | val |
---|---|---|---|
2 | 2 | 2 | 2 |
3 | 3 | 空 | 空 |
第四个 SELECT 包含 WHERE 中左表的附加条件。此条件在连接后应用,即应用于第一个 SELECT 返回的行集,并且仅返回两行。
SELECT *
FROM t1
LEFT JOIN t2 ON t1.id = t2.id
AND t1.id > 1;
SELECT * FROM t1 WHERE t1.id > 1;
id | val | id | val |
---|---|---|---|
1 | 1 | 空 | 空 |
2 | 2 | 2 | 2 |
3 | 3 | 空 | 空 |
id | val |
---|---|
2 | 2 |
3 | 3 |
第五个SELECT包含ON中左表的附加条件,应用于源表。这是另外显示的。
在 on 子句中,每行至少得到一个结果行,只要 b.value 为 null,b 行就会连接
在 where 子句中使用它,您可以跳过存在一个或多个 b 行且 b.values 都不为空的任何 a 行。
当您使用
WHERE b.value IS NULL
时,输出将只有具有b.value = NULL
的任何记录。 IE。在 B 中没有找到匹配的记录或匹配的 B 记录有value = NULL
。表 A 中的某些记录可能不会在匹配的结果中结束,并且 b.value 不为空。
虽然,如果您使用
AND b.value IS NULL
,这意味着,从B表中,只有那些记录将被选为值为空的RIGHT表输出。但是从 A 表中,所有记录都将导致输出 - 包括那些具有 b.value NOT NULL 的记录。
因此,模式 2 可能会在输出中提供更多结果。