碰巧我针对Web程序员的职位进行了很多采访。 我要问的必要问题之一是INNER JOIN与LEFT JOIN有何不同。
通常,答案是这样的:“内部联接就像集合的交集,也就是说,只有两个表中剩下的都保留,而左联接是当左边的表保持不变时,集合的交集从右边的表中添加。其他所有行均附加null。 也有可能他们画出相交的圆。
我对集合和圆圈的交集感到厌倦,以至于我什至不再纠正人。
事实是这个答案通常是不正确的。 好吧,或者至少不准确。
让我们看一下原因,同时涉及到join-s的更多细微差别。
首先,一张桌子根本不是很多。 根据数学定义,集合中的所有元素都是唯一的,不会重复,在一般情况下,在表中实际上并非如此。 第二个麻烦是术语“交叉点”只会混淆。
( 更新 。在评论中,关于集合论和唯一性的争论非常激烈。非常有趣,我学到了很多新东西,谢谢)
内联接
让我们立即举一个例子。
因此,我们将创建两个具有一个id列的相同表,在这些表中的每个表中将有两行,其值为1或其他值。
INSERT INTO table1
(id)
VALUES
(1),
(1)
(3);
INSERT INTO table2
(id)
VALUES
(1),
(1),
(2);
, , ,
SELECT *
FROM table1
INNER JOIN table2
ON table1.id = table2.id;
" ", " ", .

:
| id | id |
| --- | --- |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |

??
, CROSS JOIN. - .
CROSS JOIN — . , , 3 , — 2:
select * from t1;
id
----
1
2
3
select * from t2;
id
----
4
5
CROSS JOIN 6 .
select *
from t1
cross join t2;
id | id
----+----
1 | 4
1 | 5
2 | 4
2 | 5
3 | 4
3 | 5
, .
t1 INNER JOIN t2 ON condition
— , ,
t1 CROSS JOIN t2 WHERE condition
.. INNER JOIN
— condition
. -, , , - .
disclaimer: inner join cross join , , , : . .
LEFT JOIN
, , null, , .
, :
insert into t1
(id)
values
(1),
(1),
(3);
insert into t2
(id)
values
(1),
(1),
(4),
(5);
LEFT JOIN:
SELECT *
FROM t1
LEFT JOIN t2
ON t1.id = t2.id;
5 , , .
| id | id |
| --- | --- |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 1 | 1 |
| 3 | |
, LEFT JOIN — INNER JOIN (.. , - ), , .
LEFT JOIN :
SELECT *
FROM t1
CROSS JOIN t2
WHERE t1.id = t2.id
UNION ALL
SELECT t1.id, null
FROM t1
WHERE NOT EXISTS (
SELECT
FROM t2
WHERE t2.id = t1.id
)
, , , ..
ON
, 99% , ON id id . .
, users_stats, ip .
SELECT s.id, c.city
FROM users_stats AS s
JOIN cities_ip_ranges AS c
ON c.ip_range && s.ip
&& — (. ip4r)
ON true, CROSS JOIN
"table1 JOIN table2 ON true" == "table1 CROSS JOIN table2"
, join- . " ". , join- . .. - - php.
, , .
, , . , . , , , .
O(n!), n — . , , , . CTE; , , , , , .
, . , , 'LEFT JOIN… WHERE… IS NULL', EXISTS. , .
, . , , "".
, , , . — , , . " ". .
Update. : https://habr.com/ru/post/450528/