SQL JOIN,你想知道的应该都有
介绍
这是一篇阐述SQL JOINs的文章,本文是国内大佬翻译的一篇文章,为了更容易理解,LZ以MySQL为例在最后面加了示例,原文链接为:https://www.cnblogs.com/xufeiyang/p/5818571.html
背景
我是个不喜欢抽象的人,一图胜千言。我在网上查找了所有的关于SQL JOIN的解释,但是没有找到一篇能用图像形象描述的。
有些是有图片的但是他们没有覆盖所有JOIN的例子,有些介绍实在简单空白得不能看。所以我决定写个自己的文章来介绍SQL JOINs.
详细说明
接下来我将讨论七种你可以从两个关联表中获取数据的方法, 排除了交叉JOIN和自JOIN的情况。 七个JOINs的例子如下:
- INNER JOIN (内连接)
- LEFT JOIN (左连接)
- RIGHT JOIN (右连接)
- OUTER JOIN (外连接)
- LEFT JOIN EXCLUDING INNER JOIN (左连接排除内连接结果)
- RIGHT JOIN EXCLUDING INNER JOIN (右连接排除内连接结果)
- OUTER JOIN EXCLUDING INNER JOIN (外连接排除内连接结果)
为了这个文章更好的描述,我把5,6,7当作LEFT EXCLUDING INNER JOIN, RIGHT EXCLUDING INNER JOIN,OUTER EXCLUDING INNER JOIN来特别说明
有些人可能有不同意见: 5,6,7不是真正的两个表的JOIN; 但是为了方便理解,我仍然把这些作为JOINs, 因为你有可能会在每个查询中使用到这些 JOIN (排除一些有WHERE条件的记录)
INNER JOIN (内连接)
这是最简单、最容易理解、最常用的JOIN方式。 内连接查询返回表A和表B中所有匹配行的结果。 SQL样例如下:
SELECT <select_list>
FROM Table_A A
INNER JOIN Table_B B
ON A.Key = B.Key
LEFT JOIN (左连接)
LFET JOIN查询返回所有表A中的记录, 不管是否有匹配记录在表B中。它会返回所有表B中的匹配记录 (没有匹配的当然会标记成null了)。 SQL样例如下:
SELECT <select_list>
FROM Table_A A
LEFT JOIN Table_B B
ON A.Key = B.Key
RIGHT JOIN (右连接)
和LEFT JOIN相反。 RIGHT JOIN查询会返回所有表B中的记录,不管是否有匹配记录在表A中。它会返回所有表A中的匹配记录(没有匹配的当然会标记成null了)。 SQL样例如下:
SELECT <select_list>
FROM Table_A A
RIGHT JOIN Table_B B
ON A.Key = B.Key
OUTER JOIN (外连接)
OUTER JOIN也可以当作是FULL OUTER JOIN 或者FULL JOIN。它会返回两个表中所有行,左表A匹配右表B,右表B也匹配左表A (没有匹配的就显示null了)。OUTER JOIN一般写成下面样子:
SELECT <select_list>
FROM Table_A A
FULL OUTER JOIN Table_B B
ON A.Key = B.Key
LEFT Excluding JOIN
它会返回表A中所有不在表B中的行,一般写成:
SELECT <select_list>
FROM Table_A A
LEFT JOIN Table_B B
ON A.Key = B.Key
WHERE B.Key IS NULL
RIGHT Excluding JOIN
与上面的相反,它会返回表B中所有不在表A中的行,SQL样例如下:
SELECT <select_list>
FROM Table_A A
RIGHT JOIN Table_B B
ON A.Key = B.Key
WHERE A.Key IS NULL
OUTER Excluding JOIN
Outer Excluding JOIN 会返回所有表A和表B中没有匹配的行。我还没有遇到要用到这种情况的,但是其他的JOIN,用的比较频繁。 SQL样例如下:
SELECT <select_list>
FROM Table_A A
FULL OUTER JOIN Table_B B
ON A.Key = B.Key
WHERE A.Key IS NULL OR B.Key IS NULL
例子
以MySQL为例,准备的数据如下,为了更容易理解,所以数据比较有规律
teacher表
teacher_card表
1,2,3为teacher表独有数据,4,5,6为公有数据,7,8,9为teacher_card表独有数据
INNER JOIN
SELECT t.tid, t.name, tc.tid AS tcid, tc.description
FROM teacher t
INNER JOIN teacher_card tc
ON t.tid = tc.tid
INNER关键字可以不写
lEFT JOIN
SELECT t.tid, t.name, tc.tid AS tcid, tc.description
FROM teacher t
LEFT OUTER JOIN teacher_card tc
ON t.tid = tc.tid
OUTER关键字可以不写
RIGHT JOIN
SELECT t.tid, t.name, tc.tid AS tcid, tc.description
FROM teacher t
RIGHT OUTER JOIN teacher_card tc
ON t.tid = tc.tid
OUTER关键字可以不写
OUTER JOIN
SELECT t.tid, t.name, tc.tid AS tcid, tc.description
FROM teacher t
FULL OUTER JOIN teacher_card tc
ON t.tid = tc.tid
这样写是不行的,MySQL不支持FULL OUTER JOIN,可改写为如下形式
SELECT t.tid, t.name, tc.tid AS tcid, tc.description
FROM teacher t
LEFT JOIN teacher_card tc
ON t.tid = tc.tid
UNION
SELECT t.tid, t.name, tc.tid AS tcid, tc.description
FROM teacher t
RIGHT JOIN teacher_card tc
ON t.tid = tc.tid
LEFT EXCLUDING JOIN
SELECT t.tid, t.name, tc.tid AS tcid, tc.description
FROM teacher t
LEFT JOIN teacher_card tc
ON t.tid = tc.tid
WHERE tc.tid IS NULL
RIGHT EXCLUDING JOIN
SELECT t.tid, t.name, tc.tid AS tcid, tc.description
FROM teacher t
RIGHT JOIN teacher_card tc
ON t.tid = tc.tid
WHERE t.tid IS NULL
OUTER EXCLUDING JOIN
SELECT t.tid, t.name, tc.tid AS tcid, tc.description
FROM teacher t
FULL OUTER JOIN teacher_card tc
ON t.tid = tc.tid
WHERE t.tid IS NULL
OR tc.tid IS NULL
同理MySQL中不能写成如上形式,可改写为如下
SELECT t.tid, t.name, tc.tid AS tcid, tc.description
FROM teacher t
LEFT JOIN teacher_card tc
ON t.tid = tc.tid
WHERE tc.tid IS NULL
UNION
SELECT t.tid, t.name, tc.tid AS tcid, tc.description
FROM teacher t
RIGHT JOIN teacher_card tc
ON t.tid = tc.tid
WHERE t.tid IS NULL
最后放一张大图
文章转载自公众号:Java识堂