Left Join / IS NULL 如何消除一个 table 而另一个 table 中没有的记录?
How does Left Join / IS NULL eliminate records which are there in one table and not in the other?
我很难理解为什么 LEFT JOIN
/ IS NULL
会删除一个 table 而另一个 table 中没有的记录。
这是一个例子
SELECT l.id, l.value
FROM t_left l
LEFT JOIN t_right r
ON r.value = l.value
WHERE r.value IS NULL
为什么要r.value = NULL
删除记录?我不理解 。我知道我遗漏了一些非常基本的东西,但目前我什至无法弄清楚那个基本的东西。如果有人向我详细解释,我将不胜感激。
我想要一个非常基本的解释。
SELECT * FROM a LEFT JOIN b ON a.v = b.v ... WHERE b.id IS NULL
这是超级简单的逻辑:
- select 来自 table "a"
- join table "b"(如果存在匹配行 - ON a.v=b.v 否则使用 NULL 作为值)
- WHERE 条件:如果缺少某些内容(b.id IS NULL)= OK。
左边 returns 从左边开始的所有行 table
ON r.value = l.value
如果 l.value 没有 r.value 那么 r 是空的
r.value 为空将为真
在您的示例中,结果将是来自 t_left
的每条记录,以及来自 t_right
的每条匹配记录,它们都具有相同的 value
。如果没有匹配项,则会给出 NULL
值而不是 t_right
中的值。 where r.value is null
通过检测那些 null
值简单地消除匹配的行。
本质上是说“给我 t_left
中不匹配 t_right
中的行的行
a right join
执行与 left join
相反的顺序。
这是基于INNER JOIN
和LEFT JOIN
的区别。当您使用 INNER JOIN
时,结果仅包含两个 table 之间匹配的行(基于 ON
条件)。
但是当您使用 LEFT JOIN
时,您还会在结果中获得第一个 table 中 没有 的所有行的行第二场比赛 table。在这些情况下,第二个 table 的所有结果列都用 NULL
作为占位符填充。
然后 WHERE r.value IS NULL
测试匹配这些行。所以最终结果只包含没有匹配的行。
LEFT JOIN 获取左侧的值并尝试将左侧的 table 与 ON 指定的列相匹配,如果找不到匹配项,则解释右侧的 table的列为 NULL。因此只有那些在右边找不到匹配项的 table 才会被 IS NULL operator
选择
首先,左联接声明将包括来自左侧 table 的所有记录,并且仅包括来自右侧的匹配记录。
假设你的抽屉里有 red
、blue
和 green
袜子,而你的朋友只有 red
、yellow
和blue
,从你的抽屉到你的朋友的左连接会 return 你抽屉里的所有袜子(red
、blue
和 green
)并且只有匹配的袜子来自您的朋友(red
和 blue
)。
现在 IS NULL 部分表示您想查看抽屉中的所有袜子,而您的朋友抽屉中没有配对配对,因此在您所有的袜子中,唯一缺少一双的是 green
袜子.
这句话:
SELECT l.id, l.value
FROM t_left l
LEFT JOIN t_right r
ON r.value = l.value
会将 t_left
table 中的所有元素连接到 t_right
table 中的所有元素。正如您现在可能会看到的那样,在 INNER JOIN
中只会显示同时匹配 table 的行,因此 t_left
的行数 可能比所有行都少可能的行。在 LEFT JOIN
中,您拥有来自 t_left
table 的所有行以及来自 t_right
的匹配行(如果它们可以连接)。那么,如果 t_left 中的行不匹配任何 t_right 行,会发生什么情况? t_right table 中本应包含数据的所有字段都将填充 NULL 值。所以,如果你只从右边 table select NULL
值,你会发现 t_left
table 右边没有匹配的所有值一、XD
这可以用以下解释
mysql> select * from table1 ;
+------+------+
| id | val |
+------+------+
| 1 | 10 |
| 2 | 30 |
| 3 | 40 |
+------+------+
3 rows in set (0.00 sec)
mysql> select * from table2 ;
+------+------+
| id | t1id |
+------+------+
| 1 | 1 |
| 2 | 2 |
+------+------+
2 rows in set (0.00 sec)
这里table1.id <-> table2.t1id
现在,当我们使用连接键执行 left join
时,如果左侧 table 是 table1 那么它将从 table1 获取所有数据,并且table2 上的非匹配记录将被设置为 null
mysql> select t1.* , t2.t1id from table1 t1
left join table2 t2 on t2.t1id = t1.id ;
+------+------+------+
| id | val | t1id |
+------+------+------+
| 1 | 10 | 1 |
| 2 | 30 | 2 |
| 3 | 40 | NULL |
+------+------+------+
3 rows in set (0.00 sec)
看到 table1.id = 3 在 table2 中没有值,所以它设置为 null
当您应用 where 条件时,它将进行进一步过滤
mysql> select t1.* , t2.t1id from table1 t1
left join table2 t2 on t2.t1id = t1.id where t2.t1id is null;
+------+------+------+
| id | val | t1id |
+------+------+------+
| 3 | 40 | NULL |
+------+------+------+
1 row in set (0.00 sec)
Left join
给出左起 table 的所有记录。如果左侧 table 中存在的任何键在右侧 table 中丢失,则所有右侧 table 列将为空,但所有左侧 table 值都将存在。
这是inner join和left/right join的基本区别
因此,当您执行“r.value = null”时,您会从左侧获取那些在右侧 table.
中没有匹配键的记录
HTH.
很简单左加入基金会.....
以下查询从左侧 table 获取所有记录并从右侧 table 获取所有匹配记录,如果不匹配,它将 return NUll 值。最后,您使用 where 条件过滤数据,其中 return 值 在左侧 table 但不在右侧 table
SELECT l.id, l.value
FROM t_left l
LEFT JOIN t_right r
ON r.value = l.value
WHERE r.value IS NULL
假设 r-table 是员工,r_table 是计算机。有些员工没有电脑。部分计算机尚未分配给任何人。
内部联接:
SELECT l.*, r.*
FROM employees l
JOIN computers r
ON r.id = l.comp_id
为您提供拥有计算机的所有员工的列表,以及为每个人分配的计算机信息。没有电脑的员工将不会出现在此列表中。
左连接:
SELECT l.*, r.*
FROM employees l
LEFT JOIN computers r
ON r.id = l.comp_id
为您提供所有员工的列表。有电脑的员工会显示电脑信息。没有计算机的员工将显示 NULL 而不是计算机信息。
终于
SELECT l.*, r.*
FROM employees l
LEFT JOIN computers r
ON r.id = l.comp_id
WHERE r.id IS NULL
带 WHERE 子句的左连接将从与左连接 (2) 相同的列表开始,但它只会保留那些没有相应信息的员工电脑table,即没有电脑的员工
在这种情况下,select r
table 中的任何内容都将只是空值,因此您可以将这些字段排除在外,而 select 仅来自 select l
table:
SELECT l.*
FROM ...
尝试这个 select 序列并观察输出。每一步都建立在前一步的基础上。
请让我知道这个解释是否可以理解,或者你希望我详细说明一些。
编辑添加:
下面是创建上面使用的两个 table 的示例代码:
CREATE TABLE employees
( id INT NOT NULL PRIMARY KEY,
name VARCHAR(20),
comp_id INT);
INSERT INTO employees (id, name, comp_id) VALUES (1, 'Becky', 1);
INSERT INTO employees (id, name, comp_id) VALUES (2, 'Anne', 7);
INSERT INTO employees (id, name, comp_id) VALUES (3, 'John', 3);
INSERT INTO employees (id, name) VALUES (4, 'Bob');
CREATE TABLE computers
( id INT NOT NULL PRIMARY KEY,
os VARCHAR(20) );
INSERT INTO computers (id, os) VALUES (1,'Windows 7');
INSERT INTO computers (id, os) VALUES (2,'Windows XP');
INSERT INTO computers (id, os) VALUES (3,'Unix');
INSERT INTO computers (id, os) VALUES (4,'Windows 7');
有4名员工。贝基和约翰有电脑。安妮和鲍勃没有电脑。 (安妮有一个 comp_id 7,它不对应于计算机中的任何行 table - 所以,她实际上没有计算机。)
我很难理解为什么 LEFT JOIN
/ IS NULL
会删除一个 table 而另一个 table 中没有的记录。
这是一个例子
SELECT l.id, l.value
FROM t_left l
LEFT JOIN t_right r
ON r.value = l.value
WHERE r.value IS NULL
为什么要r.value = NULL
删除记录?我不理解 。我知道我遗漏了一些非常基本的东西,但目前我什至无法弄清楚那个基本的东西。如果有人向我详细解释,我将不胜感激。
我想要一个非常基本的解释。
SELECT * FROM a LEFT JOIN b ON a.v = b.v ... WHERE b.id IS NULL
这是超级简单的逻辑:
- select 来自 table "a"
- join table "b"(如果存在匹配行 - ON a.v=b.v 否则使用 NULL 作为值)
- WHERE 条件:如果缺少某些内容(b.id IS NULL)= OK。
左边 returns 从左边开始的所有行 table
ON r.value = l.value
如果 l.value 没有 r.value 那么 r 是空的
r.value 为空将为真
在您的示例中,结果将是来自 t_left
的每条记录,以及来自 t_right
的每条匹配记录,它们都具有相同的 value
。如果没有匹配项,则会给出 NULL
值而不是 t_right
中的值。 where r.value is null
通过检测那些 null
值简单地消除匹配的行。
本质上是说“给我 t_left
中不匹配 t_right
a right join
执行与 left join
相反的顺序。
这是基于INNER JOIN
和LEFT JOIN
的区别。当您使用 INNER JOIN
时,结果仅包含两个 table 之间匹配的行(基于 ON
条件)。
但是当您使用 LEFT JOIN
时,您还会在结果中获得第一个 table 中 没有 的所有行的行第二场比赛 table。在这些情况下,第二个 table 的所有结果列都用 NULL
作为占位符填充。
然后 WHERE r.value IS NULL
测试匹配这些行。所以最终结果只包含没有匹配的行。
LEFT JOIN 获取左侧的值并尝试将左侧的 table 与 ON 指定的列相匹配,如果找不到匹配项,则解释右侧的 table的列为 NULL。因此只有那些在右边找不到匹配项的 table 才会被 IS NULL operator
选择首先,左联接声明将包括来自左侧 table 的所有记录,并且仅包括来自右侧的匹配记录。
假设你的抽屉里有 red
、blue
和 green
袜子,而你的朋友只有 red
、yellow
和blue
,从你的抽屉到你的朋友的左连接会 return 你抽屉里的所有袜子(red
、blue
和 green
)并且只有匹配的袜子来自您的朋友(red
和 blue
)。
现在 IS NULL 部分表示您想查看抽屉中的所有袜子,而您的朋友抽屉中没有配对配对,因此在您所有的袜子中,唯一缺少一双的是 green
袜子.
这句话:
SELECT l.id, l.value
FROM t_left l
LEFT JOIN t_right r
ON r.value = l.value
会将 t_left
table 中的所有元素连接到 t_right
table 中的所有元素。正如您现在可能会看到的那样,在 INNER JOIN
中只会显示同时匹配 table 的行,因此 t_left
的行数 可能比所有行都少可能的行。在 LEFT JOIN
中,您拥有来自 t_left
table 的所有行以及来自 t_right
的匹配行(如果它们可以连接)。那么,如果 t_left 中的行不匹配任何 t_right 行,会发生什么情况? t_right table 中本应包含数据的所有字段都将填充 NULL 值。所以,如果你只从右边 table select NULL
值,你会发现 t_left
table 右边没有匹配的所有值一、XD
这可以用以下解释
mysql> select * from table1 ;
+------+------+
| id | val |
+------+------+
| 1 | 10 |
| 2 | 30 |
| 3 | 40 |
+------+------+
3 rows in set (0.00 sec)
mysql> select * from table2 ;
+------+------+
| id | t1id |
+------+------+
| 1 | 1 |
| 2 | 2 |
+------+------+
2 rows in set (0.00 sec)
这里table1.id <-> table2.t1id
现在,当我们使用连接键执行 left join
时,如果左侧 table 是 table1 那么它将从 table1 获取所有数据,并且table2 上的非匹配记录将被设置为 null
mysql> select t1.* , t2.t1id from table1 t1
left join table2 t2 on t2.t1id = t1.id ;
+------+------+------+
| id | val | t1id |
+------+------+------+
| 1 | 10 | 1 |
| 2 | 30 | 2 |
| 3 | 40 | NULL |
+------+------+------+
3 rows in set (0.00 sec)
看到 table1.id = 3 在 table2 中没有值,所以它设置为 null 当您应用 where 条件时,它将进行进一步过滤
mysql> select t1.* , t2.t1id from table1 t1
left join table2 t2 on t2.t1id = t1.id where t2.t1id is null;
+------+------+------+
| id | val | t1id |
+------+------+------+
| 3 | 40 | NULL |
+------+------+------+
1 row in set (0.00 sec)
Left join
给出左起 table 的所有记录。如果左侧 table 中存在的任何键在右侧 table 中丢失,则所有右侧 table 列将为空,但所有左侧 table 值都将存在。
这是inner join和left/right join的基本区别
因此,当您执行“r.value = null”时,您会从左侧获取那些在右侧 table.
中没有匹配键的记录HTH.
很简单左加入基金会..... 以下查询从左侧 table 获取所有记录并从右侧 table 获取所有匹配记录,如果不匹配,它将 return NUll 值。最后,您使用 where 条件过滤数据,其中 return 值 在左侧 table 但不在右侧 table
SELECT l.id, l.value
FROM t_left l
LEFT JOIN t_right r
ON r.value = l.value
WHERE r.value IS NULL
假设 r-table 是员工,r_table 是计算机。有些员工没有电脑。部分计算机尚未分配给任何人。
内部联接:
SELECT l.*, r.* FROM employees l JOIN computers r ON r.id = l.comp_id
为您提供拥有计算机的所有员工的列表,以及为每个人分配的计算机信息。没有电脑的员工将不会出现在此列表中。
左连接:
SELECT l.*, r.* FROM employees l LEFT JOIN computers r ON r.id = l.comp_id
为您提供所有员工的列表。有电脑的员工会显示电脑信息。没有计算机的员工将显示 NULL 而不是计算机信息。
终于
SELECT l.*, r.* FROM employees l LEFT JOIN computers r ON r.id = l.comp_id WHERE r.id IS NULL
带 WHERE 子句的左连接将从与左连接 (2) 相同的列表开始,但它只会保留那些没有相应信息的员工电脑table,即没有电脑的员工
在这种情况下,select
r
table 中的任何内容都将只是空值,因此您可以将这些字段排除在外,而 select 仅来自 selectl
table:SELECT l.* FROM ...
尝试这个 select 序列并观察输出。每一步都建立在前一步的基础上。
请让我知道这个解释是否可以理解,或者你希望我详细说明一些。
编辑添加: 下面是创建上面使用的两个 table 的示例代码:
CREATE TABLE employees
( id INT NOT NULL PRIMARY KEY,
name VARCHAR(20),
comp_id INT);
INSERT INTO employees (id, name, comp_id) VALUES (1, 'Becky', 1);
INSERT INTO employees (id, name, comp_id) VALUES (2, 'Anne', 7);
INSERT INTO employees (id, name, comp_id) VALUES (3, 'John', 3);
INSERT INTO employees (id, name) VALUES (4, 'Bob');
CREATE TABLE computers
( id INT NOT NULL PRIMARY KEY,
os VARCHAR(20) );
INSERT INTO computers (id, os) VALUES (1,'Windows 7');
INSERT INTO computers (id, os) VALUES (2,'Windows XP');
INSERT INTO computers (id, os) VALUES (3,'Unix');
INSERT INTO computers (id, os) VALUES (4,'Windows 7');
有4名员工。贝基和约翰有电脑。安妮和鲍勃没有电脑。 (安妮有一个 comp_id 7,它不对应于计算机中的任何行 table - 所以,她实际上没有计算机。)