MySQL 子查询、内联结、外联结

子查询
MySQL 子查询版本要求:MySQL4.1引入了对子查询的支持。
子查询:嵌套在其他查询语句中的查询。

示例: 利用子查询进行过滤
假如需要查询出成绩表分数最高的学生的姓名及编号

select st.s_no,st.s_name from student st where st.s_no in (select s1.s_no  from score s1 where s1.sc_degree  in (select max(sc.sc_degree)from score sc));

从上述查询语句可以看出,
子查询总是从内向外处理。为了执行上述子查询,MySQL实际上必须执行3条select语句,最里面的两个子查询返回学生编号和最高成绩,最外层查询返回学生信息。
子查询的查询过程一般是通过where中的in操作符来完成,in后面子查询语句查询的列即为in之前的列名。
所以在中的子句中使用子查询,应该保证select语句具有中的子句中相同数目的列。通常,子查询将返回单个列并且与单个列匹配。
使用子查询,一般与IN操作符结合使用,但可以用于测试相等(=)、不相等(<>)等。

内连接,外连接实际上都是在笛卡尔积(join)的基础上对记录进行筛选。
内联结inner join
外键:外键为某个表中的一列,它包含另一个表中的主键值,定义了两个表之间的关系。
内联结语法为:
select 查询列表
from 表1
inner join 表2
on 连接条件

sql99语法中,内联结分为以下三种:
等值联结
非等值联结
自联结

1、等值联结
示例:查询男教师及其所上的课

select tt.t_name,cc.c_name from teacher tt, course cc where  tt.t_no = cc.t_no and tt.t_sex='男';

等同于:

select tt.t_name,cc.c_name from teacher tt INNER join course cc on tt.t_no = cc.t_no where tt.t_sex='男';
image.png

select语句与前面的所有语句一样,指定要检索的列,此处最大的差别是所指定的列t_no 在两个表中都有。
在联结两个表时,实际上要做的是将第一个表中的每一行与第二个表中的每一行进行配对。where子句作为过滤条件,它只包含哪些匹配给条件(这里是联结条件)的行。没有where子句,第一个表中的每一行将第二个表中的每个行配对,而不管他们逻辑上是否可以配在一起。这也是笛卡儿积产生的原因。

什么是笛卡儿积?
由没有联结条件的表关系返回的结果为笛卡儿积,检索的行数将是第一个表中的行乘以第二个表中的行数。
下面这个图很形象的描述了笛卡儿积现象


image.png

MySQL的笛卡尔积原理
1)、先确定数据要用到哪些表。
2)、将多个表先通过笛卡尔积变成一个表。
3)、然后去除不符合逻辑的数据(根据两个表的关系去掉)。
4)、最后当做是一个虚拟表一样来加上条件即可。

2、非等值连接
示例:查询工资级别的个数>20的个数,并且按工资级别降序
select salary,grade_level,count() from
employees join job_grades on employees.salary
between job_grades.lowest_sal and job_grades.highest_sal
group by grade_level
having count(
)>20
order by grade_level desc;

3、自连接
示例:查询员工的名字包含k的员工,上级的名字
select e.last_name,m.last_name
from employees e
join employees m on e.manager_id=m.employee_id
where e.last_name like '%k%';

外联结outer join
联结包含了那些在相关表中没有关联行的行。
使用outer join 语法时,必须使用right 或left 关键字进行指定包括其所有行的表。
外连接有左连接和右连接。
左联结:查询各表中满足条件相同的行,并且查询出左表的所有信息行。
右联结:查询各表中满足条件相同的行,并且查询出右表的所有信息行。

select * from course c left OUTER JOIN score  s on c.c_no = s.c_no;  //左外连接或称左连接
image.png
select * from course c right OUTER JOIN score  s on c.c_no = s.c_no;  //右外连接或称右连接
image.png

可以看到上述查询结果的图中的数据一个是9条数据,一个是8条数据。在左联结查询时,会将左表的所有信息给查询出来,而有些数据在右表不存在,从而连带出空数据。而在右联结查询时,则是将右表的数据查询出来,然后连带出左表的部分数据。

带聚集函数的联结
聚集函数用来汇总数据。也可以与联结进行使用。
示例:查询各门课程 学习的学生人数分别是多少

select s.c_no,c.c_name,count(s.c_no) 
from score s 
INNER JOIN student t on s.s_no = t.s_no   
INNER JOIN course  c on  c.c_no = s.c_no    
GROUP BY s.c_no,c.c_name ORDER BY s.c_no desc;
image.png

说明:Select 语句使用INNER JOIN 将score、student、course表相互关联。group by 子句按课程分组数据,因此,函数调用count对每门课程学习的学生人数计数,然后返回。

总结使用联结时要注意:
保证使用正确的联结条件,否则将返回不正确的结果。
应该提供有效的联结条件,否则将会产生笛卡儿积。
在一个联结中可以包含多个表,甚至对于每个联结可以采用不同的联结类型。但是应该在一起测试他们之前,分别测试每个联结。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。