Ví dụ với bảng A và B:
A (parent) B (child)
============ =============
id | name pid | name
------------ -------------
1 | Alex 1 | Kate
2 | Bill 1 | Lia
3 | Cath 3 | Mary
4 | Dale NULL | Pan
5 | Evan
Nếu bạn muốn tìm cha mẹ và con cái của họ, bạn thực hiện INNER JOIN
:
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent INNER JOIN child
ON parent.id = child.pid
Kết quả là mọi kết quả trùng khớp của parent
id
của từ bảng bên trái và một child
của pid
từ bảng thứ hai sẽ hiển thị dưới dạng một hàng trong kết quả:
+----+--------+------+-------+
| id | parent | pid | child |
+----+--------+------+-------+
| 1 | Alex | 1 | Kate |
| 1 | Alex | 1 | Lia |
| 3 | Cath | 3 | Mary |
+----+--------+------+-------+
Bây giờ, phần trên không hiển thị các bậc cha mẹ không có con (vì id của họ không khớp với id của trẻ, vậy bạn phải làm gì? liên kết bên ngoài đầy đủ. Chúng tôi cần liên kết bên trái vì chúng tôi muốn các hàng "bổ sung" từ bảng bên trái (chính):
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent LEFT JOIN child
ON parent.id = child.pid
Kết quả là bên cạnh các trận đấu trước đó, tất cả các phụ huynh không có trận đấu (đọc:không có con) cũng được hiển thị:
+----+--------+------+-------+
| id | parent | pid | child |
+----+--------+------+-------+
| 1 | Alex | 1 | Kate |
| 1 | Alex | 1 | Lia |
| 3 | Cath | 3 | Mary |
| 2 | Bill | NULL | NULL |
| 4 | Dale | NULL | NULL |
| 5 | Evan | NULL | NULL |
+----+--------+------+-------+
Tất cả những NULL
đó ở đâu đến từ? Chà, MySQL (hoặc bất kỳ RDBMS nào khác mà bạn có thể sử dụng) sẽ không biết phải đặt gì ở đó vì những phụ huynh này không có đối sánh (con), vì vậy không có pid
cũng không phải child.name
để phù hợp với các bậc cha mẹ đó. Vì vậy, nó đặt giá trị không đặc biệt này được gọi là NULL
.
Ý của tôi là những NULL
này được tạo (trong tập kết quả) trong LEFT OUTER JOIN
.
Vì vậy, nếu chúng ta chỉ muốn hiển thị những bậc cha mẹ KHÔNG có con, chúng ta có thể thêm WHERE child.pid IS NULL
vào LEFT JOIN
bên trên. WHERE
mệnh đề được đánh giá (kiểm tra) sau JOIN
đã xong. Vì vậy, rõ ràng từ kết quả trên, chỉ có ba hàng cuối cùng mà pid
là NULL sẽ được hiển thị:
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent LEFT JOIN child
ON parent.id = child.pid
WHERE child.pid IS NULL
Kết quả:
+----+--------+------+-------+
| id | parent | pid | child |
+----+--------+------+-------+
| 2 | Bill | NULL | NULL |
| 4 | Dale | NULL | NULL |
| 5 | Evan | NULL | NULL |
+----+--------+------+-------+
Bây giờ, điều gì sẽ xảy ra nếu chúng ta di chuyển IS NULL
đó kiểm tra từ WHERE
tham gia ON
mệnh đề?
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent LEFT JOIN child
ON parent.id = child.pid
AND child.pid IS NULL
Trong trường hợp này, cơ sở dữ liệu cố gắng tìm các hàng từ hai bảng phù hợp với các điều kiện này. Đó là, các hàng mà parent.id = child.pid
VÀ child.pid IN NULL
. Nhưng nó có thể tìm thấy không có kết quả phù hợp nào như vậy vì không có child.pid
có thể bằng một cái gì đó (1, 2, 3, 4 hoặc 5) và đồng thời là NULL!
Vì vậy, điều kiện:
ON parent.id = child.pid
AND child.pid IS NULL
tương đương với:
ON 1 = 0
cái nào luôn False
.
Vì vậy, tại sao nó trả về TẤT CẢ các hàng từ bảng bên trái? Vì đó là THAM GIA TRÁI! Và các phép nối bên trái trả về hàng phù hợp (không có hàng nào trong trường hợp này) và cả các hàng từ bảng bên trái không khớp séc ( tất cả trong trường hợp này ):
+----+--------+------+-------+
| id | parent | pid | child |
+----+--------+------+-------+
| 1 | Alex | NULL | NULL |
| 2 | Bill | NULL | NULL |
| 3 | Cath | NULL | NULL |
| 4 | Dale | NULL | NULL |
| 5 | Evan | NULL | NULL |
+----+--------+------+-------+
Tôi hy vọng lời giải thích ở trên là rõ ràng.
Chú thích phụ (không liên quan trực tiếp đến câu hỏi của bạn):Tại sao trên trái đất không Pan
không xuất hiện trong các THAM GIA của chúng tôi? Bởi vì pid
của anh ấy là NULL
và NULL trong logic (không phổ biến) của SQL không bằng bất kỳ thứ gì nên nó không thể khớp với bất kỳ id mẹ nào (là 1,2,3,4 và 5). Ngay cả khi có NULL ở đó, nó vẫn không khớp vì NULL
không bằng bất cứ thứ gì, thậm chí không bằng NULL
chính nó (đó là một logic rất kỳ lạ, thực sự!). Đó là lý do tại sao chúng tôi sử dụng kiểm tra đặc biệt IS NULL
và không phải là = NULL
kiểm tra.
Vì vậy, sẽ Pan
hiển thị nếu chúng tôi thực hiện RIGHT JOIN
? Nó sẽ được thôi! Bởi vì THAM GIA PHẢI sẽ hiển thị tất cả các kết quả khớp (THAM GIA BÊN TRONG đầu tiên mà chúng tôi đã thực hiện) cộng với tất cả các hàng từ bảng RIGHT không khớp (trong trường hợp của chúng tôi là một, (NULL, 'Pan')
hàng.
SELECT id, parent.name AS parent
, pid, child.name AS child
FROM
parent RIGHT JOIN child
ON parent.id = child.pid
Kết quả:
+------+--------+------+-------+
| id | parent | pid | child |
+---------------+------+-------+
| 1 | Alex | 1 | Kate |
| 1 | Alex | 1 | Lia |
| 3 | Cath | 3 | Mary |
| NULL | NULL | NULL | Pan |
+------+--------+------+-------+
Rất tiếc, MySQL không có FULL JOIN
. Bạn có thể thử nó trong các RDBMS khác và nó sẽ hiển thị:
+------+--------+------+-------+
| id | parent | pid | child |
+------+--------+------+-------+
| 1 | Alex | 1 | Kate |
| 1 | Alex | 1 | Lia |
| 3 | Cath | 3 | Mary |
| 2 | Bill | NULL | NULL |
| 4 | Dale | NULL | NULL |
| 5 | Evan | NULL | NULL |
| NULL | NULL | NULL | Pan |
+------+--------+------+-------+