SQL系列(十)—— 联结(join)

在数据库设计中,基本上都是根实体ER关系和范式设计多张表。这样更能设计出更合理、紧凑的表结构,提高有效数据存储,数据的管理维护更简便,也提高了库表的伸缩性。

但是事物总是平衡的,在很多场景中单张表的数据不能满足需求,需要根据多张关联表的数据逻辑关系,返回关联数据。如:查询选修了英语课程的所有学生信息。这里就涉及到学生和课程实体的之间的关联关系。这种查询必然需要操作两张表:

  1. 可以分步骤多次查询
  2. 也可以使用前面提到的子查询

但是这两种方式性能不如:联结。这也是多张表的带来的弊端:SQL的复杂化,DBMS需要更强的功能支持。

join是将多张表混合在一起根据数据之间的逻辑关系进行查询操作。联结的类型很多:

  • 自联结
  • 自然联结(等值联结或者内连接)
  • 外链接

自联结:同一张表使用别名和自己进行连接查询
自然连接:多张表使用逻辑关联列进行进行联结查询,只查询出关联列在多张表完全相等的数据,多张表中对于的未关联上的数据不在查询结果中。
外联结:针对上述自然连接,如果需要将未关联上的行也需要查询,即是外联结。外联结根据查询出不同表的未关联的数据,又分为:左联结、右联结、全联结。

下面看个例子:

前提:

create table student (stu_id int, stu_name varchar(10), stu_age smallint);
create table course(course_id int, course_name varchar(10));
create table score(stu_id int, course_id int, score float);

insert into student(stu_id, stu_name, stu_age) values (1, 'xx', 15),(2, 'dd', 17),(3, 'zz', 18);
insert into student(stu_id, stu_name, stu_age) values (4, 'gg', 15);

insert into course(course_id, course_name) values (1, 'shuxue'),(2, 'yuwen'),(3, 'yingyu'),(4, 'wuli'),(5, 'huaxue');
insert into score(stu_id, course_id, score) values (1, 1, 87.5),(1, 2, 79.7),(1, 3, 90.3),(1, 4, 89.1),(1, 5, 91.4);
insert into score(stu_id, course_id, score) values (2, 1, 71.4),(2, 2, 56.3),(2, 3, 78.4),(2, 4, 89.1),(2, 5, 93.2);
insert into score(stu_id, course_id, score) values (3, 1, 59.4),(3, 2, 40.3),(3, 3, 25.4),(3, 4, 100),(3, 5, 98.9);

insert into score(stu_id, course_id, score) values (4, 1, 16.0),(4, 2, 20.5),(4, 3, 19.4);

-- 查询英语成绩在90分及以上的学生

select stu.* from student as stu, score as sco where stu.stu_id = sco.stu_id and sco.course_id = 3 and sco.score >= 90;

-- 查询每个学生的所有课程的分数

select tmp.stu_name, tmp.score, cos.course_name from (select stu.stu_name, sco.score, sco.course_id from student as stu left outer join score as sco on stu.stu_id = sco.stu_id) as tmp left outer join course as cos on tmp.course_id = cos.course_id order by tmp.stu_name, tmp.score;

自联结和内联结时,条件子句一般使用where,在外联结中多数使用on子句。

内联结:可以直接在from子句后用逗号分割表名,亦可以使用inner join关键字联结表名
左联结:可以使用left join或者left outer join关键字联结表名
右联结:可以使用right join或者rigth outer join关键字联结表名
全连接:可以使用full join或者full outer join关键字联结表名

下面再来看下区别几种外联结的区别:

-- 左联结
select stu.*, sco.course_id, sco.score from student as stu left join score as sco on stu.stu_id = sco.stu_id;

结果:

stu_id stu_name stu_age course_id score
1 xx 15 1 87.5
1 xx 15 2 79.7
1 xx 15 3 90.3
1 xx 15 4 89.1
1 xx 15 5 91.4
2 dd 17 1 71.4
2 dd 17 2 56.3
2 dd 17 3 78.4
2 dd 17 4 89.1
2 dd 17 5 93.2
3 zz 18 1 59.4
3 zz 18 2 40.3
3 zz 18 3 25.4
3 zz 18 4 100
3 zz 18 5 98.9
4 gg 15 1 16
4 gg 15 2 20.5
4 gg 15 3 19.4
5 mm 28 NULL NULL

可以看出最后一行中关于分数的部分全是null,这就是左联结的特点,如果左边表的数据在右边无法连接,则全部补null。

右联结同理,这里就不再赘述。

参考

《SQL必知必会》

猜你喜欢

转载自www.cnblogs.com/lxyit/p/9329632.html