MySQL-03-多表查询
排序 ORDER BY
排序语句,将要显示的数据按照自己要求的规则进行排序。
将 SELECT 出来的数据,按照指定的列值进行排序,ASC 为从小到大,DESC 为从大到小,如果不写排序方式,则默认为 ASC,从小到大。
ASC全称ascend ,为升序的意思,即从小到大。
DESC全程descend,为降序的意思,即从大到小。
1 | select * from "table" |
如果 ORDER BY
后面有多个列,则满足 column1 的排序规则后,对于 column1 相等的列则进行 column2 的排序。
排序依据
对于 ORDER BY 后面跟着 FROM 表里面的 column 的,就可以直接找到对应的数据,作为排序依据。
如果利用关系子查询返回的内容作为排序依据,那么则会执行子查询,返回结果作为本行的排序依据。
分页 LIMIT
用来只显示一段指定的查询出来的结果,只能放在语句末尾。
基本用法
LIMIT [位置偏移量,] 行数
- 第一个 “位置偏移量” 参数指示 MySQL 从哪一行开始显示,是一个可选参数,如果不指定 “位置偏移量” ,将会从表中的第一条记录开始(第一条记录的位置偏移量是 0,第二条记录的位置偏移量是 1,以此类推);第二个参数 “行数” 指示返回的记录条数。
1 | --前10条记录: |
优势
约束返回结果的数量可以 减少数据表的网络传输量
,也可以 提升查询效率
。如果我们知道返回结果只有 1 条,就可以使用 LIMIT 1
,告诉 SELECT 语句只需要返回一条记录即可。这样的好处就是 SELECT 不需要扫描完整的表,只需要检索到一条符合条件的记录即可返回。
多表查询概念
多表查询,也称为关联查询,指两个或更多个表一起完成查询操作。
前提条件:这些一起查询的表之间是有关系的(一对一、一对多),它们之间一定是有关联字段。
通过多表查询可以从多个表得到对应的完整数据,比如:
1 | SELECT table1.a table2.b FROM table1, table2。 |
举个栗子:
我们有员工表和部门表,我们想要知道所有员工的部门信息(员工对部门为 多对一 关系),就需要多表查询。
1 | SELECT employees.last_name, departments.department_name -- 要查询的信息为两个表的列 |
多表查询-表名前缀
因为是多表查询,所以可能会涉及到两个表有字段名字相同,所以可以在表中有相同列时,在列名之前加上表名前缀来区分。
1 | SELECT table1.a table2.b FROM table1, table2。 |
多表查询-分类
等值连接 和 非等值连接
是看两个表的连接条件是否为 相等。
等值连接:连接条件为字段的值相等。
非等值连接:连接条件为非相等符号,一般来说是一个区间范围。
比如,工资等级表 和 员工工资 进行连接,那就是 员工工资 满足 工资等级表 的两个值之间的范围就可以连接起来:
1 | SELECT e.last_name, e.salary, j.grade_level |
自连接 和 非自连接
非自连接:就是这里的多表查询,利用了表之间的 N 对 N 关系(除了自我引用以外的所有关系)。
自连接:单表查询,但是连接的对象是一张表里面的两个字段。利用了这张表的自我引用的关系。
比如,一张表里面有所有的人信息,我们想要通过每个人的 manager_id 和 其他人的 employee_id 进行连接,从而获取每个人的上司的名字,整个过程是一个表的自连接:
1 | SELECT concat(worker.last_name ,' works for ' |
内连接 和 外连接
内连接: 合并具有同一列的两个以上的表的行, 结果集中不包含一个表与另一个表不匹配的行,也就是不满足 WHERE 条件的其他所有行数据,都不会出现在结果中。
外连接: 两个表在连接过程中除了返回满足连接条件的行以外还返回左(或右)表中不满足条件的行 ,这种连接称为左(或右) 外连接。没有匹配的行时, 结果表中相应的列为空(NULL)。
如果是左外连接,则连接条件中左边的表也称为
主表
,右边的表称为从表
。如果是右外连接,则连接条件中右边的表也称为
主表
,左边的表称为从表
。
内连接可用 WHERE 直接连接,或者 Inner Join ON 连接。
外连接用 Left/Right Join On 进行。
多表查询-笛卡尔积错误
笛卡尔乘积是一个数学运算。假设我有两个集合 X 和 Y,那么 X 和 Y 的笛卡尔积就是 X 和 Y 的所有可能组合,也就是第一个对象来自于 X,第二个对象来自于 Y 的所有可能。组合的个数即为两个集合中元素个数的乘积数。
如果在多表查询中,出现了部分行或者全部行的数据进行了笛卡尔积组合,那么就说明这个多表查询出现了连接错误。可能原因:
- 省略多个表的连接条件(或关联条件)
- 连接条件(或关联条件)无效
- 所有表中的所有行互相连接
比如:
1 | SELECT employees.last_name, departments.department_name |
查询结果为两个表所有行数据组合,数量为两个表的行数乘积。
如果加上连接条件,结果就是 多对一 中多的那个行数了:
1 | SELECT employees.last_name, departments.department_name |
连接条件是用来消除不符合要求的笛卡尔积组合的,如果连接条件没有设好,那么就会出现不符合要求的笛卡尔积组合。
多表查询实现(99 标准)
1 | SELECT 字段列表 |
多个表之间的连接查询,只需要 table 1 join table2 之后,再将结果 join table3 就实现了三个表的连接:
1 | SELECT table1.column, table2.column,table3.column |
内查询
1 | SELECT employees.last_name, departments.department_name |
或者:
1 | SELECT employees.last_name, departments.department_name |
外查询
假设我们要查询 employees A departments B 两个表的 employee_id last_name department_name 数据。
下面是对上图的一个实现:
- 中图:内连接 A∩B
1 | SELECT A.employee_id, A.last_name, B.department_name |
- 左上图:左外连接
1 | SELECT A.employee_id, A.last_name, B.department_name |
- 右上图:右外连接
1 | SELECT A.employee_id, A.last_name, B.department_name |
- 左中图:A - A∩B
1 | SELECT A.employee_id, A.last_name, B.department_name |
- 右中图:B-A∩B
1 | SELECT A.employee_id, A.last_name, B.department_name |
- 左下图:满外连接
1 | -- 左上+右中 |
- 右下图
1 | -- 左中+右中 |
多表查询练习
要首先判断目标为某个表 or 两个表的全体成员还是 两个表的有链接成员。(及判断是否需要一部分为 NULL 的数据),从而确定是 OUTER JOIN 还是 INNER JOIN。
员工表:employees;
部门表:departments;
位置表:locations;
- 显示 所有 员工的姓名,部门号和部门名称。
1 | -- 因为是 所有 员工,所以要覆盖员工所有数据,即使没有连接在部门的那部分。 |
- 选择所有有奖金的员工的 last_name , department_name , location_id , city
1 | -- 因为还是 所有 员工,所以两次 join 都要保留 emp 表 数据。 |
- 选择指定员工的姓名,员工号,以及他的管理者的姓名和员工号(都在 employees 里),结果类似于下面的格式
1 | employees Emp manager Mgr |
多表查询中的自连接查询,也就是建立连接的是一张表内的两个不同但有关系的字段(员工 id 和它的上司 id)。
1 | SELECT emp.last_name AS `employees`, emp.employee_id AS Emp, man.last_name AS `manager`, man.employee_id AS Mgr |
- 查询哪个城市没有部门
因为是看那个城市没有部门,所以关注的是 城市 中,无法和部门建立连接的数据,locations 放在 left join 的左边,显示所有城市数据(尤其是连接后 部门相关信息为 null 的)。
1 | SELECT loc.city |