目录
创建三张有关联的表
创建20级学生表
创建学生对应的学校表
创建学校地址表
多表查询
查询1:内连接--table [inner] join table on 条件
查询2:左外连接 left [outer] join
查询3:右外连接 right [outer] join
查询4:满外连接union [all]
三张表的内外连接
内连接
左外连接
右外连接
满外连接
在对表格进行处理时,我们所需要的信息不都是放在同一张表格上的,mysql作为关系型的数据库,在库中的数据表两个之间或多或少的存在联系,比方说,一张学生表可以关联一张学校表,一张学校表可以关联一张学校地址表,因此我们再访问查看学生表时,如果想要同时也查看到学生的学校时就会进行多表查询。
创建三张有关联的表
创建20级学生表
包含有学生id即学生学号,学生姓名,学生排名,学生成绩,学生德育分,学生智育分,学生综合分,学生所在的学校id。如下学生有53位(其中赵六同学上报了一个没有学校名字的id--7):
SQL语句:
CREATE TABLE IF NOT EXISTS 20student(stu_id INT,stu_name VARCHAR(20),stu_pai INT,stu_score DOUBLE,stu_get1 DOUBLE ,stu_get2 DOUBLE,stu_total DOUBLE,sch_id INT);
INSERT INTO 20student VALUES(23,"张孟泽",1,95.35,100,92.25,100.0,1);
INSERT INTO 20student VALUES(1,"范佳慧",2,94.98,100,91.96,99.0,1);
INSERT INTO 20student VALUES(16,"徐豪",3,94.73,100,91.21,100.0,1);
INSERT INTO 20student VALUES(17,"傅荣添",4,93.68,95,91.14,100.0,1);
INSERT INTO 20student VALUES(2,"周安奈尔",5,93.45,99,90.42,97.5,1);
INSERT INTO 20student VALUES(12,"方梓懿",6,92.69,99,88.11,100.0,1);
INSERT INTO 20student VALUES(4,"盛哲",7,91.89,100,92.81,81.0,1);
INSERT INTO 20student VALUES(36,"黄少军",8,90.56,97,87.94,92.0,1);
INSERT INTO 20student VALUES(7,'翁芝燕',9,90.19,100,87.99,87.0,2);
INSERT INTO 20student VALUES(31,'徐坚翔',10,90.14,100,85.56,94.0,2);
INSERT INTO 20student VALUES(47,'陈维羽',11,89.61,98,84.51,96.5,3);
INSERT INTO 20student VALUES(21,'竺夏',12,89.56,100,86.77,87.5,3);
INSERT INTO 20student VALUES(5,'高楹',13,87.85,100,90.08,69.0,3);
INSERT INTO 20student VALUES(13,'陈子昕',14,87.43,97,91.77,65.0,3);
INSERT INTO 20student VALUES(11,'龚忠梅',15,87.33,96,86.42,81.5,2);
INSERT INTO 20student VALUES(10,'陈家兴',16,86.68,100,83.96,81.5,4);
INSERT INTO 20student VALUES(14,'骆梦盈',17,85.89,97,87.31,70.5,3);
INSERT INTO 20student VALUES(27,'金建勇',18,85.73,99,84.51,76.5,4);
INSERT INTO 20student VALUES(8,'庞如仪',19,84.78,100,87.3,62.0,4);
INSERT INTO 20student VALUES(35,'沈驰',20,84.19,92,82.64,81.0,3);
INSERT INTO 20student VALUES(39,'谢世杰',21,83.42,100,82.36,70.0,2);
INSERT INTO 20student VALUES(48,'张金豪',22,82.85,100,82.14,68.0,1);
INSERT INTO 20student VALUES(24,'李阳',23,82.84,78,84.26,83.5,3);
INSERT INTO 20student VALUES(32,'朱斌鸿',24,82.76,100,80.44,72.5,2);
INSERT INTO 20student VALUES(26,'张景棋',25,81.94,100,83.56,59.0,2);
INSERT INTO 20student VALUES(18,'李晟',26,81.66,89,86.74,59.5,2);
INSERT INTO 20student VALUES(6,'黄家佳',27,81.66,98,82.27,63.5,1);
INSERT INTO 20student VALUES(3,'章楠',28,81.46,85,85.39,66.5,3);
INSERT INTO 20student VALUES(22,'朱威',29,80.92,98,79.45,68.3,3);
INSERT INTO 20student VALUES(9,'刘琦',30,80.40,94,83.19,58.5,4);
INSERT INTO 20student VALUES(15,'林森',31,80.32,79,84.26,70.0,4);
INSERT INTO 20student VALUES(29,'黄建豪',32,79.75,92,81.91,61.0,4);
INSERT INTO 20student VALUES(20,'王昕洋',33,79.48,100,80.13,57.0,2);
INSERT INTO 20student VALUES(30,'周越',34,79.18,91,77.46,72.5,1);
INSERT INTO 20student VALUES(34,'罗杰文',35,78.69,100,76.15,65.0,2);
INSERT INTO 20student VALUES(50,'陈楠杰',36,77.86,100,68.85,82.8,3);
INSERT INTO 20student VALUES(49,'李浩然',37,77.45,98,77.41,57.0,4);
INSERT INTO 20student VALUES(25,'李芝博',38,77.40,94,77.84,59.5,4);
INSERT INTO 20student VALUES(38,'王腾逸',39,76.92,96,75.86,61.0,1);
INSERT INTO 20student VALUES(33,'徐琪安',40,76.89,100,75.82,57.0,2);
INSERT INTO 20student VALUES(45,'陈佳栋',41,76.70,100,74.66,59.5,4);
INSERT INTO 20student values(28,'王必成',42,76.18,95,75.96,58.0,1);
INSERT INTO 20student VALUES(40,'萧方威',43,75.26,98,73.77,57.0,2);
INSERT INTO 20student VALUES(43,'范力达',44,75.16,87,75.77,61.5,1);
INSERT INTO 20student VALUES(44,'何健',45,72.99,90,71.81,59.5,2);
INSERT INTO 20student VALUES(46,'童琳凯',46,71.70,95,66.5,64.0,4);
INSERT INTO 20student VALUES(42,'顾康',47,71.66,70,74.16,66.0,3);
INSERT INTO 20student VALUES(19,'吴路凯',48,70.82,72,75.04,57.0,4);
INSERT INTO 20student VALUES(41,'郑贻轩',49,67.58,80,66.13,59.5,1);
INSERT INTO 20student VALUES(51,'张三',51,67.58,80,66.13,59.5,5);
INSERT INTO 20student VALUES(52,'李四',52,67.58,80,66.13,59.5,6);
INSERT INTO 20student VALUES(53,'王五',50,67.58,80,66.13,59.5,6);
INSERT INTO 20student VALUES(54,'赵六',53,67.58,80,66.13,59.5,7);
创建学生对应的学校表
学校表中有id,name,location_id三个字段。
SQL语句:
CREATE TABLE IF NOT EXISTS school(sch_id INT ,sch_name VARCHAR(20),sch_location_id INT);
INSERT INTO school VALUES(1,"浙江大学",1);
INSERT INTO school VALUES(2,"杭州电子科技学院",2);
INSERT INTO school VALUES(3,"绍兴文理学院",3);
INSERT INTO school VALUES(4,"温州理工学院",4);
INSERT INTO school VALUES(5,"蓝翔技师学院",5);
INSERT INTO school VALUES(6,null,6);
创建学校地址表
包含有学校地址id,学校坐落的城市
SQL语句:
CREATE TABLE IF NOT EXISTS sch_location(sch_location_id INT,sch_location_place VARCHAR(150));
INSERT INTO sch_location VALUES(1,"浙江省杭州市");
INSERT INTO sch_location VALUES(2,"浙江省杭州市");
INSERT INTO sch_location VALUES(3,"浙江省绍兴市");
INSERT INTO sch_location VALUES(4,"浙江省温州市");
INSERT INTO sch_location VALUES(5,NULL);
INSERT INTO sch_location VALUES(6,NULL);
多表查询
当我们在进行多表查询时,需要将多张表名写在一起,如果后面不加where条件的话就有笛卡尔积错误,如select 字段名 from 表1,表2; #得到结果集(记录集)将是表1的数据×表2的数据。
如下我们的学生表有57条数据,学校表有6条数据,不加条件直接查询的话,结果就是57×6=342条数据
select stu_name,sch_name from 20student,school ;
因此我们如果不想要出现笛卡尔积这种的结果的话,在后面加上我们的条件即可。
select stu_name,sch_name from 20student,school where 20student.sch_id=school.sch_id ;
查询1:内连接--table [inner] join table on 条件
内连接只会匹配并显示出两张表都符合条件的数据,如果有些数据没有匹配到的话就会省略掉。
现在我们要查询出学生的学号,姓名,以及其所对应的学校名
可以使用SQL语句:select stu_id, stu_name,sch_name from 20student,school where 20student.sch_id=school.sch_id ;
也可以使用SQL语句:select stu_id, stu_name,sch_name from 20student as stu join school as sch on stu.sch_id=sch.sch_id ;
如下我们的搜索结果为52条记录
我们的内连接的结果集中是不包含我们学生表与学校表不匹配的行,而学校id只有[1,2,3,4,5,6],没有匹配的行,因此不会显示出来信息。
我们在查询数据数据时,如果是从n张表中查找数据的话,写的where条件至少要有n-1个,如果少于n-1个条件的话就会出现笛卡尔积 错误。如下,我们有三张表做连接:
我们的三张图可以写上两个条件来使得他们三相连:
现在我们需要的记录为:学生的id,学生姓名,学生的学校名字及学校的位置,并按照id升序排序
SELECT t1.stu_id,t1.stu_name,t2.sch_name,t3.sch_location_place
FROM 20student AS t1,school AS t2,sch_location AS t3
WHERE t1.`sch_id`=t2.`sch_id`
AND t2.`sch_location_id`=t3.`sch_location_id`
ORDER BY t1.`stu_id`;
如上的结果集我们也可以使用内连接的方式来实现:
SELECT t1.stu_id,t1.stu_name,t2.sch_name,t3.sch_location_place
FROM 20student AS t1 JOIN school AS t2 ON t1.`sch_id`=t2.`sch_id`
JOIN sch_location AS t3 ON t2.`sch_location_id`=t3.`sch_location_id`
ORDER BY t1.`stu_id`;
如果有图形化工具的话推荐使用图形化工具(有语句自动补充的功能),如下:
查询2:左外连接 left [outer] join
如果我们想要让赵六同学的信息也显示出来,可以使用左外连接----哪边数据多出来了就用哪边的方向,在我们的表中,学生表的信息与学校表的信息相比多出来了一个赵六的信息不匹配,而我们的学生表在上面案例中是写在join左边的,因此我们使用的是左外连接。
使用SQL语句:select stu_id, stu_name,sch_name from 20student as stu left join school as sch on stu.sch_id=sch.sch_id ;
查询3:右外连接 right [outer] join
右外连接和左外连接的使用差不多,只是这次我们数据多的表到了join右边。
接下来我们不仅要查询学生id,学生姓名,学生的学校,还要查询学校的地址--关联第三张表。
查询4:满外连接union [all]
在Oracle中满外连接和左右外连接的使用差不多,只是将left/right变成了full,虽然在我们的MySQL中是不支持这种语法的,但是我们可以使用union或union all关键字来连接两个筛选好的结果集以达到我们想要的满外连接效果。我们使用满外连接得到的结果集不仅有左表不满足的行,也有右表不满足的行,值得注意的是:在合并两个表时,对应的列数和数据类型必须相同,并且相互对应,语法格式:
select 字段名,字段名,字段名........from 表名
union [all]
select 字段名,字段名,字段名........from 表名;
union all先比union少了查找重复的操作,因此union all的查找速度要快些。
因此在MySQL中,union all所需要的资源比union语句少,在SQL优化的角度来看,如果明确知道合并后的数据结果集不存在重复的数据或者是不需要去除重复的数据,相当于我们下图的图三与图六(或图二与图五)相加的结果(这两组图可以直接使用union all来进行查找数据)。则尽量使用union all语句,可以提高数据查询的效率。
现在我们去使用满外连接,得到既有不符合A集合的结果集也有不符合B集合的结果集,其结果集的数据为A+B+C。分析:我们可以先得到赵六这个数据1条与内连接的数据集相加(52条数据)---即左外连接(共53条数据),之后我们再去得到只有学校id但没有学校名的数据即学校名为null的结果集(共2条),经过联合union all后我们可以得到55条数据
三张表的内外连接
现在我们有三张表,只有54条数据是相互匹配的:
如果我们要对其进行关联查找数据的话有四种连接方式:内连接,左外连接,右外连接,满外连接。得到的数据应如下图所示的数量:
内连接
从三张表中查找出学生id,学生姓名,学校名,学校位置,并按照学生id排序:
SELECT t1.stu_id,t1.stu_name,t2.sch_name,t3.sch_location_place
FROM 20student AS t1 LEFT JOIN school AS t2 ON t1.`sch_id`=t2.`sch_id`
LEFT JOIN sch_location AS t3 ON t2.`sch_location_id`=t3.`sch_location_id`
ORDER BY stu_id;
左外连接
现在我们从三张表中查找出学生id,学生姓名,学校名,学校位置,按照学生id排序并且将学生表中没有学校的同学名字也显示出来:
SELECT t1.stu_id,t1.stu_name,t2.sch_name,t3.sch_location_place
FROM 20student AS t1 LEFT JOIN school AS t2 ON t1.`sch_id`=t2.`sch_id`
LEFT JOIN sch_location AS t3 ON t2.`sch_location_id`=t3.`sch_location_id`
ORDER BY stu_id;
右外连接
SELECT t1.stu_id,t1.stu_name,t2.sch_name,t3.sch_location_place
FROM 20student AS t1 JOIN school AS t2 ON t1.`sch_id`=t2.`sch_id`
RIGHT JOIN sch_location AS t3 ON t2.`sch_location_id`=t3.`sch_location_id`
ORDER BY stu_id ;
满外连接
-- 左外连接
SELECT t1.stu_id,t1.stu_name,t2.sch_name,t3.sch_location_place
FROM 20student AS t1 LEFT JOIN school AS t2 ON t1.`sch_id`=t2.`sch_id`
LEFT JOIN sch_location AS t3 ON t2.`sch_location_id`=t3.`sch_location_id`
UNION ALL
-- 不包含左边数据表的记录
-- 右外连接
SELECT t1.stu_id,t1.stu_name,t2.sch_name,t3.sch_location_place
FROM 20student AS t1 LEFT JOIN school AS t2 ON t1.`sch_id`=t2.`sch_id`
RIGHT JOIN sch_location AS t3 ON t2.`sch_location_id`=t3.`sch_location_id`
WHERE t2.`sch_location_id` IS NULL;
如果有问题的话请在评论区留言。