声明一下:博文内容中的SQL语句都使用 MySQL 5.6.25 版本通过测试,博文内容侧重于对SQL理论的理解,对于不同的数据库实现或是SQL版本,可能会存在一些差异!
数据库表连接大致分为三种:交叉连接、内连接、外连接
交叉连接(CROSS JOIN):其实就是内连接的一种特例,不带查询条件
内连接(INNER JOIN):相等连接、不等连接、自然连接
外连接(OUTER JOIN):左外联接、右外链接、全外连接(全外连接只有部分RDBMS系统可以做到,例如 Oracle 、SQL Server。做不到的例如 MySQL、Access)
交叉连接
最简单,返回多张表每一行相乘的结果,也就是笛卡尔积。关键字是 CROSS JOIN。交叉连接从定义上讲,应该是不带连接条件的,但是实际上有些数据库(例如 MySQL)允许在 CROSS JOIN 后面加上连接条件,这个时候就和内联接的效果一样了。
1 SELECT * FROM tb_person CROSS JOIN tb_book;
内连接
相等连接:就是条件使用等值符号(=)
不等连接:就是条件使用不等符号(>,>=,<,<=,!>,!<,<>)
自然连接:只有在两张表中含有相同的列名称时,才能使用自然连接,自然连接默认利用同名列构造出相等连接,实际用处并不大。
1 SELECT * FROM tb_person INNER JOIN tb_book ON tb_person.id = tb_book.person_id; -- 相等连接 2 SELECT * FROM tb_person INNER JOIN tb_book ON tb_person.id <> tb_book.person_id; -- 不等连接 3 SELECT * FROM tb_person NATURAL JOIN tb_book; -- 自然连接
JOIN 到底是不是 INNER JOIN 的简写形式?
1 SELECT * FROM tb_person JOIN tb_book;
查阅《SQL权威指南》第四版,发现:JOIN 是SQL-92标准加入的一种新语法,是SQL的表连接操作,在SQL语句中如果使用 JOIN 操作符,但是又没有指定 JOIN 类型,那么就隐式使用 INNER 类型。
我的理解是 JOIN 本身就是SQL语法的一部分,可以独立存在,并不依附于谁,说 JOIN 是 INNER JOIN 的简写,似乎有些缩小范围。说 JOIN 默认使用 INNER 类型可能会更好一些。当然每个人的理解的角度可能不一样,说它是简写也好,不是简写也好,都没有太大关系,重要的是理解它,会使用。
外连接
注重两张表之间的关系,也就是表的左右顺序,通常称之为左表和右表。
左外连接(LEFT OUTER JOIN):接收左表中的每一行,并利用这些行与右表匹配,找出右表中符合条件的行,最终连接形成数据结果集。如果对于左表行记录右表找不到能与之匹配的行记录,就会使用NULL替代右表,得到连接匹配结果。当左表与右表具有一对多关系时,左外联接特别有用。
右外连接(RIGHT OUTER JOIN):与左外联接是相同的道理,只是右表占主导地位而已。如果把左外联接中的左表和右表互换位置,得到的就是右外连接的结果。
全外连接(FULL OUTER JOIN):综合了左外连接和右外连接的特性,左表和右表地位相同,左表无匹配数据用NULL替代,右表无匹配数据也用NULL替代,也就是说左表和右表的数据都会在查询结果里面,不会少数据。
1 SELECT * FROM tb_person LEFT OUTER JOIN tb_book ON tb_person.id = tb_book.person_id; 2 SELECT * FROM tb_person LEFT JOIN tb_book ON tb_person.id = tb_book.person_id; -- 简写 3 4 SELECT * FROM tb_person RIGHT OUTER JOIN tb_book ON tb_person.id = tb_book.person_id; 5 SELECT * FROM tb_person RIGHT JOIN tb_book ON tb_person.id = tb_book.person_id; -- 简写 6 7 -- 外联接不是每一种数据库都有的特性 8 SELECT * FROM tb_person FULL OUTER JOIN tb_book ON tb_person.id = tb_book.person_id; 9 SELECT * FROM tb_person FULL JOIN tb_book ON tb_person.id = tb_book.person_id; -- 简写
ON 和 WHERE 的区别
可能有些朋友发现了这样一个问题,下面两句 SQL 得到的结果是一样的
1 SELECT * FROM tb_person INNER JOIN tb_book ON tb_person.id = tb_book.person_id; 2 SELECT * FROM tb_person INNER JOIN tb_book WHERE tb_person.id = tb_book.person_id;
以前我没有深入理解 ON 和 WHERE 的区别,经过2#提点,查询资料及实际测试后,我发现在某些情况下,它们可能会得到相同的结果,但是理论上它们是不一样的,就好比“条条道路通罗马”,最终的目的虽然是一样的,但是每条路是不一样的。
首先明确一点,SQL在连接表的时候,大部分情况下,都会产生一张中间表,用于返回数据结果。
ON 用于表与表之间的连接操作,是连接条件,在SQL执行连接,产生中间表的时候用到,此时还没有得到最终的数据结果。
WHERE 是SQL得到最终中间表,也就是的数据结果后,对数据进行筛选的时候用到,是筛选条件。
正确的使用 ON 和 WHERE ,可以优化SQL,提高SQL的执行效率。