MySQL基础笔记(8)多表查询

一.多表关系介绍

        项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也会存在着各种联系,分为如下3类:

  • 一对一
  • 一对多或者多对一
  • 多对多

一对一:

  • 用户与用户详情的关系
  • 常见于单表的拆分,以提高工作效率——将一张表中一部分的信息放在一张表中,其他详细的信息则放在另一张表中
  • 在任意一方加入外键关联另一方的主键,并且为外键设置唯一约束unique~

一对多:

  • 一个员工只能在一个部门,但一个部门可以有多个员工
  • 实现:在的一方建立外键,指向的一方的主键

多对多:

  • 一个学生可以学多门课,每门课也可以被多个 学生学

MySQL基础笔记(8)多表查询_第1张图片

  • 实现:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键
  • DataGrip有不错的可视化功能(下图)

MySQL基础笔记(8)多表查询_第2张图片

二.概述

最基础的多表查询写法:

select * from student,class;

        查询的多张表只需要用逗号分别隔开,但是此时查出来的数据并无什么实际意义:假设有50个学生,6个课程,则会查出来50*6=300条记录——相当于互相匹配,也就是学生会学全部的课,而每一门课都会被所有的学生学。该情况称为笛卡尔积。

笛卡尔积是指:数学中的集合A和集合B所有的组合情况。在多表查询中,需要消除无效的笛卡尔积

将上述的SQL语句改为:

select * from student,class where student.dept_id=class.id;

 其中id是class表的主键,dept_id为student关联class主键的外键。

多表查询的分类:

1.连接查询

  • 内连接:查询A、B两表交集部分的数据
  • 外连接:左外查询左表和交集,右外查询右表和交集
  • 自连接:只有一张表,与自身进行连接查询(必须使用表别名

MySQL基础笔记(8)多表查询_第3张图片

2.子查询

三.内连接

1.隐式内连接

select emp.name,dept.name from emp,dept where emp.dept_id=dept.id;

在多表查询时为了方便书写,经常采用起别名的形式。(紧随其后加空格即可)

select e.name,d.name from emp e,dept d where e.dept_id=d.id;

2.显式内连接

select e.name,d.name from emp e inner join dept d on e.dept_id=d.id;
  • inner可以直接省略
  • on后面加的是去除笛卡尔积的条件 

四.外连接

1.左外连接
select 字段列表 from 表1 left [outer] join 表2 on 条件...;
2.右外连接
select 字段列表 from 表1 right [outer] join 表2 on 条件;

(实际开发中左外连接用的更多,在不改变业务需求的情况下直接将两表对调顺序即可~) 

(要求查询结果完全包含哪个,就将其作为查询偏向的一侧

五.自连接

select 字段列表 from 表A 别名A join 表A 别名B on 条件...;

(在用到自连接的场合里,往往需要将目标的一张表拆分为逻辑上的两张表~) 

六.联合查询union

把多次查询的结果合并起来,形成一个新的查询结果集。

select 字段列表 from 表A……
union [all]
select 字段列表 from 表B……
  • 如果将union all 改成 union ,则会去除重复的字段
  • 需要注意的是,只有查询字段一致时才能使用联合查询

七.子查询

SQL语句中嵌套select语句,就叫做子查询,又称为嵌套查询~

select * from t1 where column = (select column 1 from t2);

外部的sql语句,可以是insert、update、delete、select中的任何一个~ 

根据查询结果的不同,将子查询分为:

  • 标量子查询:查询结果为单个值
  • 列子查询:子查询结果为一列
  • 行子查询:子查询结果我一行
  • 表子查询:子查询结果为多行多列

根据子查询的位置:又可以分为where、from、select之后的子查询~ 

八.标量子查询

返回的结果是单个值,最简单的形式~

本质上是两步的查询过程一次性合并为一步~

        当某种需要的条件暂时没有显式表出时,可以采用标量子查询将该条件作为标量查询出来,然后再将该标量作为目标条件再次查询~

select * from emp where dept_id = (select id from dept where name='软件工程');

九.列子查询

列子查询返回的结果是一列,即结果可以有很多行~

常见的操作符有:in、not in、any、some、all~

MySQL基础笔记(8)多表查询_第4张图片

同理,比如此处查询计算机科学与技术和软件工程的全部学生的信息: 

select * from emp where depi_id in(select id from dept where name='计科'
or name='软工');

再比如,选出所有考研数学一成绩比所有计科和软工学生都要高的人的信息:

select * from student where num>all(select num from student where depi_id in
(select id from dept where name='计科'or name='软工'));

 容易犯低级错误的地方是:子查询的SQL语句不需要加额外的分号!

十.行子查询

结果会返回一行,即可以是多列共存~

如下:查询出所有俱乐部和国籍均与穆勒相同的球员信息~ 

select * from emp where (country,club)=(select country,club from player where 
name='托马斯穆勒');

十一.表子查询

常用于from之后——将表子查询的结果作为一张新的临时表,再度进行查询~常用的操作符为in~

MySQL基础笔记(8)多表查询_第5张图片 

道理相同,不再赘述~要注意的是:由于结果有多个,所以常用in而不能用等于号~ 

你可能感兴趣的:(MySQL,笔记,sql,mysql)