SQL JOINS 总结
首先一图总结各种 SQL JOINS:
接下来我们以下面的两个表为例,一个一个讲解
(注:以下内容均在Oracle下进行,文末会提到MySQL和Oracle的区别):
Table A:
Table B:
(INNER) JOIN
内连接,非常的简单啊,就是两个表的交集:
注意这些连接都需要指定 ON 关键字,表示连接条件(关于 ON 和 NATURAL、USING 的区别后面再说)。
对上面俩表使用 INNER JOIN(SQL语句中INNER可以省略):
SELECT *
FROM A INNER JOIN B
ON A.course_id = B.course_id;
输出结果如下,可以看到这里的course_id是原来两个表共有的(并且由于ON关键字的特性,这里的两个course_id并未被合并,这一点我们之后会详细解释):
LEFT (OUTER) JOIN
左外连接,先左后外。也就是先把Table A整个copy来再说,再在Table B中找有没有匹配的部分,没有匹配的部分就用NULL代替:
对上面俩表使用 LEFT JOIN:
SELECT *
FROM A LEFT JOIN B
ON A.course_id = B.course_id;
输出结果如下,可以看到结果中含有Table A的全部内容,并且由于Table B中没有course_id=2的元组,所以在teacher_name属性内为NULL:
RIGHT (OUTER) JOIN
右外连接,先右后外。也就是先把Table B整个copy来再说,再在Table A中找有没有匹配的部分,没有匹配的部分就用NULL代替,整个过程和左外连接一致:
对上面俩表使用 RIGHT JOIN:
SELECT *
FROM A RIGHT JOIN B
ON A.course_id = B.course_id;
输出结果如下,可以看到结果中含有Table B的全部内容,并且由于Table A中没有course_id=4的元组,所以在teacher_name属性内显示NULL:
FULL OUTER JOIN
全外连接,就是将左边和右边嗯塞一起,空的部分就填上NULL,也是非常简单:
对上面俩表使用 FULL OUTER JOIN:
SELECT *
FROM A FULL OUTER JOIN B
ON A.course_id = B.course_id;
输出结果如下,可以看到结果中含有Table A和Table B的全部内容,俩表各自没有的部分都显示为NULL:
其他情况的连接
这张图中还展示了一些其他的连接方式,其实已经没有新东西了,都是上述四种连接的结合,更具体地说,是三种外连接去掉内连接的情况:
可以看到,这三种连接都使用了WHERE子句,保证另一个表中必有NULL值(也就是另一个表中没有的部分)。以LEFT JOIN的情况为例,对上面俩表进行操作:
SELECT *
FROM A LEFT JOIN B
ON A.course_id = B.course_id
WHERE B.course_id IS NULL;
输出结果如下,意为只在Table A中有,而Table B中没有的元组:
RIGHT JOIN和FULL OUTER JOIN的情况也差不多,兹不赘述(应该……不需要吧?)
NATURAL关键字
除此之外你可能还会见到一种连接方式,就是NATURAL JOIN。
其实NATURAL JOIN并不是一种单独的连接方式,而是NATURAL关键字在起作用,它代表着自动查询两张表中所有相同的字段,然后再进行等值连接。
例如上面的INNER JOIN代码可以重写成如下形式:
SELECT *
FROM A NATURAL JOIN B;
因为两表中只有course_id相同,所以这段语句的运行效果就等同于前面的INNER JOIN,但在显示格式上有所区别!
可以看出相较于ON,NATURAL将相同的course_id合并了,在观感上和存储上显然都是更合适的。
但要注意的是,如果两个表之间存在多个相同字段,而我们只想根据某一个相同字段进行查询时,还是得老老实实写ON。
除了NATURAL JOIN之外,也可以有NATURAL LEFT JOIN,NATURAL FULL OUTER JOIN等,总之NATURAL就是ON的简易替换,并且在显示上稍有区别。
例如以下是NATURAL LEFT JOIN的查询结果:
USING关键字
除了NATURAL外,我们还可以使用USING指定需要以其为根据的相同字段。
例如还是INNER JOIN的例子,我们可以重写成如下形式:
SELECT *
FROM A JOIN B
USING(course_id);
也是同样的效果,并且显示结果上和NATURAL JOIN相同,都起到了一个对选定属性集“去重”的作用:
对NATURAL,ON,USING三者可以总结如下:
NATURAL:选中所有相同属性集、去重
USING:选中所有指定的相同属性集、对这些指定属性集去重(对于没有指定的相同属性集则不会去重)
ON:选中所有指定的相同属性集、不去重
CROSS JOIN
使用该连接返回两表的笛卡尔积。
非常普通,普通到了没有存在的必要。
例如下面的两条语句执行起来是一样的。。。
SELECT *
FROM A CROSS JOIN B;
SELECT *
FROM A, B;
都是两个表的笛卡尔积:
当然我们可以通过加入WHERE子句使其变为等值连接。例如下面的语句和INNER JOIN是等价的:
SELECT *
FROM A, B
WHERE A.course_id = B.course_id;
ON和WHERE
虽然等值条件既可以在ON中写,也可以在WHERE中写,不过因为ON只充当连接条件,而WHERE主要充当选择/过滤条件,因此还是建议将ON和WHERE区分开来。
MySQL中的JOIN
MySQL的JOIN语法与Oracle大致相同,但仍有微小的区别。
首先在Oracle中,INNER JOIN必须跟上ON关键字,否则无法执行;但是在MySQL中INNER JOIN没有ON的话,则表示两个表的笛卡尔积:
其次MySQL不支持FULL OUTER JOIN,可以使用LEFT JOIN UNION RIGHT JOIN的方式替代(Oracle中也可以这么写):
SELECT *
FROM A LEFT JOIN B
ON A.course_id = B.course_id
UNION
SELECT *
FROM A RIGHT JOIN B
ON A.course_id = B.course_id;
查询结果如下(不得不说MySQL的可视化做得比Oracle好一万倍。。。)