在做毕业设计时,对数据库的查询用到了多表查询, 之前学的一知半解的,借着这个机会,又查了些资料,复习了一下,记录下来,以便日后用到时能快速解决问题。
下面实例中用到的是
MySQL:mysql-5.7.13-winx64,
工具是Navicat for MySQL
数据和工具不同时,注意语法的区别
1.1 多表连接有哪些分类?
1.2 针对这些分类有哪些连接方法?
1.3 这些连接方法分别作用于哪些应用场景?
针对这三个点通过实例来讲述,目的是穷尽所有的场景和所有的方法,并且对每个方法的使用做实例。
首先先列举用到的分类(内连接,外连接,交叉连接)和连接方法(如下):
A)内连接:join,inner join(两者效果一样)
B)外连接:left join,left outer join,right join,right outer join,union
C)交叉连接:cross join
二.下面以实例进行分析
两张假设有两张表格A和B,把表格当作一个集合,那么表格中的记录就是集合中的一个元素。
两张表格如下:
Table A:
Table B:
2.1 内连接(只有一种场景)
inner join 或者join(等同于inner join)
SELECT a.*, b.* FROM A a //a为表A的别名,下面b类似
JOIN B b
ON a.id = b.id //约束条件
结果如下:
其中a.* b.* 表示结果显示包括表A和表B的全部字段,也可自定义要显示的字段(直接用别名.字段名,中间用逗号隔开)from后的表的字段在结果的前面,其中a为表A的别名,b为表B的别名,需要在第一次提到表名的后面声明,之后就可以使用别名代替表名称。应用场景:取表A和表B的交集
条件是on定义的约束,这种场景下得到的是满足某一条件的A,B内部的数据;正因为得到的是内部共有数据,所以连接方式称为内连接。
2.2 外连接(六种场景)
2.2.1 left join 或者left outer join(等同于left join)
SELECT a.*, b.* FROM A a
LEFT JOIN B b
ON a.id = b.id
结果如下,Table B中不存在的记录填充Null:
left join的显示结果依赖于left join前面的表格,同理right join依赖于后面的表格
应用场景:
这种场景下得到的是A的所有数据,和满足某一条件的B的数据;
2.2.2 [left join 或者left outer join(等同于left join)] + [where B.column is null]
SELECT a.id aid,a.age, b.id bid, b.name FROM A a
LEFT JOIN B b
ON a.id = b.id
WHERE b.id is NULL
其中由于表A和表B中有相同的字段id,所以在查询时为结果定义要显示的字段的名称,其中a.id的结果用aid 字段表示,where后再次筛选的条件,非空用b.id is not null
结果如下:
应用场景:
这种场景下得到的是A中的所有数据减去”与B满足同一条件 的数据”,然后得到的A剩余数据;
2.2.3 right join 或者fight outer join(等同于right join)
SELECT a.id aid,a.age, b.id bid, b.name FROM A a
RIGHT JOIN B b
ON a.id = b.id
结果如下,TableB中的数据全部显示,Table A中不存在的记录填充Null:
应用场景:
这种场景下得到的是B的所有数据,和满足某一条件的A的数据;
2.2.4 [left join 或者left outer join(等同于left join)] + [where A.column is null]
SELECT a.id aid,a.age, b.id bid, b.name FROM A a
RIGHT JOIN B b
ON a.id = b.id
WHERE a.id is NULL
结果如下:
应用场景:
这种场景下得到的是B中的所有数据减去 “与A满足同一条件 的数据“,然后得到的B剩余数据;
2.2.5 full join (mysql不支持,但是可以用 left join union right join代替)
SELECT a.id aid,a.age, b.id bid, b.name FROM A a
LEFT JOIN B b
ON a.id = b.id
UNION
SELECT a.id aid,a.age, b.id bid, b.name FROM A a
RIGHT JOIN B b
ON a.id = b.id
union过后,重复的记录会合并(id为2,3,4的三条记录),所以结果如下:
应用场景:
这种场景下得到的是满足某一条件的公共记录,和独有的记录
2.2.6 full join + is null(mysql不支持,但是可以用 (left join + is null) union (right join+isnull代替)
SELECT a.id aid,a.age, b.id bid, b.name FROM A a
LEFT JOIN B b
ON a.id = b.id
WHERE b.id is NULL
UNION
SELECT a.id aid,a.age, b.id bid, b.name FROM A a
RIGHT JOIN B b
ON a.id = b.id
WHERE a.id is NULL
结果如下:
应用场景:
这种场景下得到的是A,B中不满足某一条件的记录之和
注:上面共有其中七(2^3-1)种应用场景,还有一种是全空白,那就是什么都不查,七种情形包含了实际应用所有可能的场景
2.3 交叉连接 (cross join)
2.3.1 实际应用中还有这样一种情形,想得到A,B记录的排列组合,即笛卡儿积,这个就不好用集合和元素来表示了。需要用到cross join:
SELECT a.id aid,a.age, b.id bid, b.name FROM A a
CROSS JOIN B b
结果如下:
2.3.2 还可以为cross join指定条件 (where):
SELECT a.id aid,a.age, b.id bid, b.name FROM A a
CROSS JOIN B b
WHERE a.id = b.id
结果如下;
注:这种情况下实际上实现了内连接的效果
三 注意事项
上面仍然存在遗漏,那就是mysql对sql语句的容错问题,即在sql语句不完全符合书写建议的情况,mysql会允许这种情况,尽可能地解释它:
3.1 一般cross join后面加上where条件,但是用cross join+on也是被解释为cross join+where;
3.2 一般内连接都需要加上on限定条件,如上面场景2.1;如果不加会被解释为交叉连接;
3.3 如果连接表格使用的是逗号,会被解释为交叉连接;
注:sql标准中还有union join和natural inner join,mysql不支持,而且本身也没有多大意义,其结果可以用上面的几种连接方式得到