SQL JOIN 全解析:用 users
與 orders
表徹底掌握內連接、左連接、右連接
在日常開發中,SQL 的連接(JOIN)語句是數據庫查詢的核心技能。尤其在多表聯合查詢時,不掌握好 INNER JOIN
、LEFT JOIN
、RIGHT JOIN
,你就很容易寫出“行數膨脹”、數據丟失、NULL
滿天飛的奇怪結果。
本文將用兩張簡單的表 users
(用戶)和 orders
(訂單)作為例子,深入講解三種常見的連接方式。
一、準備工作:建表與數據
我們先創建兩張表并插入一些測試數據。
表結構:
-- 用戶表:左表
CREATE TABLE users (id INT PRIMARY KEY,name VARCHAR(50)
);-- 訂單表:右表
CREATE TABLE orders (id INT PRIMARY KEY,user_id INT,item VARCHAR(100),FOREIGN KEY (user_id) REFERENCES users(id)
);
示例數據:
-- 插入用戶數據
INSERT INTO users (id, name) VALUES
(1, '孫悟空'),
(2, '蘇有朋'),
(3, '李白'),
(4, '趙云'),
(5, '諸葛亮');-- 插入訂單數據
INSERT INTO orders (id, user_id, item) VALUES
(101, 1, '金箍棒'),
(102, 2, '琵琶'),
(103, 1, '筋斗云'),
(104, 99, '無主之劍'); -- 注意:user_id=99 不存在于 users 中
二、INNER JOIN:內連接
SELECT a.id, a.name, b.item
FROM users a
INNER JOIN orders b ON a.id = b.user_id;
結果:
id | name | item |
---|---|---|
1 | 孫悟空 | 金箍棒 |
2 | 蘇有朋 | 琵琶 |
1 | 孫悟空 | 筋斗云 |
特點:
- 只保留能成功匹配的記錄。
user_id=99
的訂單匹配不到 → 被排除。李白
、趙云
、諸葛亮
沒下單 → 被排除。孫悟空
有兩個訂單 → 出現兩次。
總結一句話:
內連接 = 兩邊都有才要。
三、LEFT JOIN:左連接
SELECT a.id, a.name, b.item
FROM users a
LEFT JOIN orders b ON a.id = b.user_id;
結果:
id | name | item |
---|---|---|
1 | 孫悟空 | 金箍棒 |
1 | 孫悟空 | 筋斗云 |
2 | 蘇有朋 | 琵琶 |
3 | 李白 | NULL |
4 | 趙云 | NULL |
5 | 諸葛亮 | NULL |
特點:
- 保留所有左表(users)數據。
- 匹配不到的訂單信息 → 填充為
NULL
。 user_id=99
的訂單仍然被丟棄。
總結一句話:
左連接 = 左邊全保,右邊能連就連,不能連就補 NULL。
四、RIGHT JOIN:右連接
SELECT a.id, a.name, b.item
FROM users a
RIGHT JOIN orders b ON a.id = b.user_id;
結果:
id | name | item |
---|---|---|
1 | 孫悟空 | 金箍棒 |
1 | 孫悟空 | 筋斗云 |
2 | 蘇有朋 | 琵琶 |
NULL | NULL | 無主之劍 |
特點:
- 保留所有右表(orders)數據。
- 匹配不到的用戶信息 → 補
NULL
。 user_id=99
沒用戶匹配 → 仍然出現在結果中。
總結一句話:
右連接 = 右邊全保,左邊對不上就補 NULL。
五、膨脹現象:JOIN 會讓行數增加嗎?
是的!比如:
SELECT a.*, b.*
FROM users a
LEFT JOIN orders b ON a.id = b.user_id;
你可能以為每個用戶只出現一行,結果 孫悟空
出現了兩次。
原因:
JOIN
會對滿足條件的所有組合都生成結果。孫悟空
有兩個訂單 → 出現兩行。趙云
沒下單 → 也會保留一行(item=NULL
)。
小貼士:
連接時不是“找一個就停”,而是“所有匹配的都拿出來”。
六、常見場景推薦
場景 | 推薦 JOIN |
---|---|
只看有訂單的用戶 | INNER JOIN |
列出所有用戶 + 他們的訂單情況 | LEFT JOIN |
列出所有訂單 + 是否找到下單用戶 | RIGHT JOIN |
查出哪些用戶沒有下單 | LEFT JOIN + WHERE b.id IS NULL |
示例:
SELECT a.id, a.name
FROM users a
LEFT JOIN orders b ON a.id = b.user_id
WHERE b.id IS NULL;
結語
- JOIN 本質上是“表之間的行配對”,不只是挑字段而已。
- 行數會膨脹,尤其是一對多、多對多連接時尤為明顯。
- 熟練掌握 JOIN,才能寫出既高效又準確的 SQL 查詢。
一圖了解JOIN
參考鏈接
-
SQL Joins Visualizer
一目了然地展示各種 JOIN 類型行為。 -
LeetCode SQL Tutorial(JOIN 練習)
通過實戰題目鞏固 JOIN 和子查詢等知識點。 -
W3Schools:SQL JOIN
基礎入門首選,配有圖解和在線練習。 -
MySQL JOIN 語法官方文檔
官方介紹各種 JOIN 的語法規則和性能提示。 -
PostgreSQL JOIN Types
PostgreSQL 對 JOIN 的詳細描述,適用于所有標準 SQL 數據庫。 -
Join Data In SQL