关于 JOIN 耐心总结,学不会你打我系列( 二 )

SQL92笛卡尔积(交叉连接)笛卡尔积是一个数学上的概念,表示如果存在 X,Y 两个集合,则 X,Y 的笛卡尔积记为 X * Y. 表示由 X,Y 组成有序对的所有情况 。
对应在 SQL 中,就是将两张表中的每一行进行组合 。而且在连接时,可以没有任何限制,可将没有关联关系的任意表进行连接 。
这里拿学生表和班级表举例,在学生表中我们插入了20名学生的数据,课程表中插入三个班级 。则学生和班级的笛卡尔结果就是将两表的每行数据一一组合,最后就是有 24 * 3 = 72 行的结果,如下图所示 。
并且需要知道的是,下面学习的外连接,自连接,等值连接等都是在笛卡尔积的基础上筛选得到的 。
对应的 SQL92 写法为:
select * from Student, Class;

关于 JOIN 耐心总结,学不会你打我系列

文章插图
 
等值连接(内连接)等值连接就是将两张表中都存在的列进行连接,具体来说就是 where 后面通过 = 进行筛选 。
比如查询 Student 和其所属 Class 信息的关系:
SELECT * FROM Student as s, Class as c where s.class_id = c.id;
关于 JOIN 耐心总结,学不会你打我系列

文章插图
 
非等值连接非等值连接就是将等值连接中的等号换成其他的过滤条件 。
比如这里查询每个班级的信息以及所属的班级类别 。
SELECT * FROM Class as c, ClassType t where c.number between t.minimum_number and maximum_number;
关于 JOIN 耐心总结,学不会你打我系列

文章插图
 
外连接对于 SQL92 的外连接来说,在连接时会将两张表分为主表和从表,主表显示所有的数据,从表显示匹配到的数据,没有匹配到的则显示 None. 用 + 表示从表的位置 。
左外连接:左表是主表,右表时从表 。
SELECT * FROM Student as s , Class as c where s.class_id = c.id(+);右外连接:左表是从表,右表时主表 。
SELECT * FROM Class as c, Student as swhere c.id = s.class_id(+);注意 SQL92 中并没有全外连接 。
自连接自连接一般用于连接本身这张表,由于常见的 DBMS 都会对自连接做一些优化,所以一般在子查询和自连接的情况下都使用自连接 。
比如想要查询比1年1班人数多的班级:
子查询:
SELECT * FROM Class WHERE number > (SELECT number FROM Class WHERE name="1年1班"); 自连接:
SELECT c2.* FROM Class c1, Class c2 WHERE c1.number < c2.number and c1.name = "1年1班";
关于 JOIN 耐心总结,学不会你打我系列

文章插图
 
SQL99交叉连接SELECT * FROM Student CROSS JOIN Class;还可以对多张表进行交叉连接,比如连接 Student,Class,ClassType 三张表,结果为 24 * 3 * 3 = 216 条 。
相当于嵌套了三层 for 循环 。
关于 JOIN 耐心总结,学不会你打我系列

文章插图
 
自然连接其实就是 SQL92 中的等值连接,只不过连接的对象是具有相同列名,并且值也相同的内容 。
SELECT * FROM Student NATURAL JOIN CLASS;SELECT * FROM Student as s, Class as c where s.id = c.id;如果想用 NATURAL JOIN 时,建议为两表设置相同的列名,比如 Student 表中的班级列为 class_id, 则在 Class 表中,id 也应改为 class_id. 这样连接更合理一些 。
如果大家尝试,自然连接的话,会发现查出来的结果集为空,不要奇怪,下面说一下原因:
关于 JOIN 耐心总结,学不会你打我系列

文章插图
 
这是因为,NATURAL JOIN 会自动连接两张表中相同的列名,而对于 Student 和 Class 两张表来说,id 和 name 在这两张表都是相同的,所以既满足 id 又满足 name 的行是不存在的 。
相当于 SQL 变成了这样
SELECT * FROM Student as s, Class as c where s.id = c.id and s.name = c.name;ON 连接ON 连接其实对了 SQL92 中的等值连接和非等值连接:
等值连接:
SELECT * FROM Student as s JOIN Class as c ON s.class_id = c.id;orSELECT * FROM Student as s INNER JOIN Class as c ON s.class_id = c.id;非等值连接:
SELECT * FROM Class as c JOIN ClassType t ON c.number between t.minimum_number and maximum_number;USING 连接和 NATURAL JOIN 很像,可以手动指定具有相同列名的列进行连接:
SELECT * FROM Student JOIN Class USING(id);
关于 JOIN 耐心总结,学不会你打我系列


推荐阅读