【MySQL】10. 复合查询(重点)

本文涉及的产品
云数据库 RDS MySQL,集群版 2核4GB 100GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用版 2核4GB 50GB
简介: 【MySQL】10. 复合查询(重点)

复合查询(重点)

前面我们讲解的mysql表的查询都是对一张表进行查询,在实际开发中这远远不够。

1. 基本查询回顾

数据还是使用之前的雇员信息表
在标题7的位置!

mysql> select * from emp where sal > 500 or job = 'MANAGER';
+--------+--------+-----------+------+---------------------+---------+---------+--------+
| empno  | ename  | job       | mgr  | hiredate            | sal     | comm    | deptno |
+--------+--------+-----------+------+---------------------+---------+---------+--------+
| 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20 |
| 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30 |
| 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30 |
| 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20 |
| 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30 |
| 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30 |
| 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10 |
| 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20 |
| 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10 |
| 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30 |
| 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20 |
| 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30 |
| 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20 |
| 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10 |
+--------+--------+-----------+------+---------------------+---------+---------+--------+
14 rows in set (0.00 sec)

查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J

# 可以用like模糊匹配的方法
mysql> select * from emp where (sal > 500 or job = 'MANAGER') and ename like 'J%';
+--------+-------+---------+------+---------------------+---------+------+--------+
| empno  | ename | job     | mgr  | hiredate            | sal     | comm | deptno |
+--------+-------+---------+------+---------------------+---------+------+--------+
| 007566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL |     20 |
| 007900 | JAMES | CLERK   | 7698 | 1981-12-03 00:00:00 |  950.00 | NULL |     30 |
+--------+-------+---------+------+---------------------+---------+------+--------+
2 rows in set (0.00 sec)
# 也可以用substring函数取字符
mysql> select * from emp where (sal>500 or job = "MANAGER") and substring(ename,1,1) = 'J';
+--------+-------+---------+------+---------------------+---------+------+--------+
| empno  | ename | job     | mgr  | hiredate            | sal     | comm | deptno |
+--------+-------+---------+------+---------------------+---------+------+--------+
| 007566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL |     20 |
| 007900 | JAMES | CLERK   | 7698 | 1981-12-03 00:00:00 |  950.00 | NULL |     30 |
+--------+-------+---------+------+---------------------+---------+------+--------+
2 rows in set (0.00 sec)

按照部门号升序而雇员的工资降序排序

mysql> select * from emp order by deptno asc, sal desc;
+--------+--------+-----------+------+---------------------+---------+---------+--------+
| empno  | ename  | job       | mgr  | hiredate            | sal     | comm    | deptno |
+--------+--------+-----------+------+---------------------+---------+---------+--------+
| 007839 | KING   | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 |    NULL |     10 |
| 007782 | CLARK  | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 |    NULL |     10 |
| 007934 | MILLER | CLERK     | 7782 | 1982-01-23 00:00:00 | 1300.00 |    NULL |     10 |
| 007788 | SCOTT  | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 |    NULL |     20 |
| 007902 | FORD   | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 |    NULL |     20 |
| 007566 | JONES  | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 |    NULL |     20 |
| 007876 | ADAMS  | CLERK     | 7788 | 1987-05-23 00:00:00 | 1100.00 |    NULL |     20 |
| 007369 | SMITH  | CLERK     | 7902 | 1980-12-17 00:00:00 |  800.00 |    NULL |     20 |
| 007698 | BLAKE  | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 |    NULL |     30 |
| 007499 | ALLEN  | SALESMAN  | 7698 | 1981-02-20 00:00:00 | 1600.00 |  300.00 |     30 |
| 007844 | TURNER | SALESMAN  | 7698 | 1981-09-08 00:00:00 | 1500.00 |    0.00 |     30 |
| 007521 | WARD   | SALESMAN  | 7698 | 1981-02-22 00:00:00 | 1250.00 |  500.00 |     30 |
| 007654 | MARTIN | SALESMAN  | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 |     30 |
| 007900 | JAMES  | CLERK     | 7698 | 1981-12-03 00:00:00 |  950.00 |    NULL |     30 |
+--------+--------+-----------+------+---------------------+---------+---------+--------+
14 rows in set (0.00 sec)

使用年薪进行降序排序

mysql> select (sal*12+comm) as 年薪 from emp order by 年薪;
+----------+
| 年薪     |
+----------+
|     NULL |
|     NULL |
|     NULL |
|     NULL |
|     NULL |
|     NULL |
|     NULL |
|     NULL |
|     NULL |
|     NULL |
| 15500.00 |
| 16400.00 |
| 18000.00 |
| 19500.00 |
+----------+
14 rows in set (0.00 sec)
这里年薪为NULL的原因是因为有些员工的奖金为NULLNULL值是不参与计算的,所以这里需要用到之前学到的函数ifnull()

mysql> select ename, (sal*12+ifnull(comm,0)) as 年薪 from emp order by 年薪 desc;
+--------+----------+
| ename  | 年薪     |
+--------+----------+
| KING   | 60000.00 |
| SCOTT  | 36000.00 |
| FORD   | 36000.00 |
| JONES  | 35700.00 |
| BLAKE  | 34200.00 |
| CLARK  | 29400.00 |
| ALLEN  | 19500.00 |
| TURNER | 18000.00 |
| MARTIN | 16400.00 |
| MILLER | 15600.00 |
| WARD   | 15500.00 |
| ADAMS  | 13200.00 |
| JAMES  | 11400.00 |
| SMITH  |  9600.00 |
+--------+----------+
14 rows in set (0.00 sec)

显示工资最高的员工的名字和工作岗位

mysql> select ename, job from emp where sal = (select max(sal) from emp );
+-------+-----------+
| ename | job       |
+-------+-----------+
| KING  | PRESIDENT |
+-------+-----------+
1 row in set (0.00 sec)

显示工资高于平均工资的员工信息

mysql> select * from emp where sal > (select avg(sal) from emp );
+--------+-------+-----------+------+---------------------+---------+------+--------+
| empno  | ename | job       | mgr  | hiredate            | sal     | comm | deptno |
+--------+-------+-----------+------+---------------------+---------+------+--------+
| 007566 | JONES | MANAGER   | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL |     20 |
| 007698 | BLAKE | MANAGER   | 7839 | 1981-05-01 00:00:00 | 2850.00 | NULL |     30 |
| 007782 | CLARK | MANAGER   | 7839 | 1981-06-09 00:00:00 | 2450.00 | NULL |     10 |
| 007788 | SCOTT | ANALYST   | 7566 | 1987-04-19 00:00:00 | 3000.00 | NULL |     20 |
| 007839 | KING  | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 | NULL |     10 |
| 007902 | FORD  | ANALYST   | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL |     20 |
+--------+-------+-----------+------+---------------------+---------+------+--------+
6 rows in set (0.00 sec)

显示每个部门的平均工资和最高工资

mysql> select deptno, avg(sal) 平均工资, max(sal) 最高工资 from emp group by deptno;
+--------+--------------+--------------+
| deptno | 平均工资     | 最高工资     |
+--------+--------------+--------------+
|     10 |  2916.666667 |      5000.00 |
|     20 |  2175.000000 |      3000.00 |
|     30 |  1566.666667 |      2850.00 |
+--------+--------------+--------------+
3 rows in set (0.00 sec)

mysql> select deptno, format(avg(sal), 2) , max(sal) from emp group by deptno;
+--------+---------------------+----------+
| deptno | format(avg(sal), 2) | max(sal) |
+--------+---------------------+----------+
|     10 | 2,916.67            |  5000.00 |
|     20 | 2,175.00            |  3000.00 |
|     30 | 1,566.67            |  2850.00 |
+--------+---------------------+----------+
3 rows in set (0.00 sec)

显示平均工资低于2000的部门号和它的平均工资

mysql> select deptno,format(avg(sal),2) 平均工资 from emp group by deptno having 平均工资 <2000;
+--------+--------------+
| deptno | 平均工资     |
+--------+--------------+
|     10 | 2,916.67     |
|     20 | 2,175.00     |
|     30 | 1,566.67     |
+--------+--------------+
3 rows in set (0.00 sec)

显示每种岗位的雇员总数,平均工资

mysql> select job, count(*) ,format(avg(sal),2) 平均工资 from emp group by job;
+-----------+----------+--------------+
| job       | count(*) | 平均工资     |
+-----------+----------+--------------+
| ANALYST   |        2 | 3,000.00     |
| CLERK     |        4 | 1,037.50     |
| MANAGER   |        3 | 2,758.33     |
| PRESIDENT |        1 | 5,000.00     |
| SALESMAN  |        4 | 1,400.00     |
+-----------+----------+--------------+
5 rows in set (0.00 sec)

2. 多表查询

实际开发中往往数据来自不同的表,所以需要多表查询。
本节我们用一个简单的公司管理系统,有三张表EMP,DEPT,SALGRADE来演示如何进行多表查询。
案例:
显示雇员名、雇员工资以及所在部门的名字因为上面的数据来自EMP和DEPT表,因此要联合查询
在这里插入图片描述
其实我们只要emp表中的deptno = dept表中的deptno字段的记录

mysql> select emp.ename, emp.sal, dept.dname, dept.deptno from emp,dept where emp.deptno = dept.deptno;
+--------+---------+------------+--------+
| ename  | sal     | dname      | deptno |
+--------+---------+------------+--------+
| SMITH  |  800.00 | RESEARCH   |     20 |
| ALLEN  | 1600.00 | SALES      |     30 |
| WARD   | 1250.00 | SALES      |     30 |
| JONES  | 2975.00 | RESEARCH   |     20 |
| MARTIN | 1250.00 | SALES      |     30 |
| BLAKE  | 2850.00 | SALES      |     30 |
| CLARK  | 2450.00 | ACCOUNTING |     10 |
| SCOTT  | 3000.00 | RESEARCH   |     20 |
| KING   | 5000.00 | ACCOUNTING |     10 |
| TURNER | 1500.00 | SALES      |     30 |
| ADAMS  | 1100.00 | RESEARCH   |     20 |
| JAMES  |  950.00 | SALES      |     30 |
| FORD   | 3000.00 | RESEARCH   |     20 |
| MILLER | 1300.00 | ACCOUNTING |     10 |
+--------+---------+------------+--------+
14 rows in set (0.00 sec)

显示部门号为10的部门名,员工名和工资

mysql> select dname,ename,sal from emp,dept where emp.deptno = dept.deptno and emp.deptno = '10';
+------------+--------+---------+
| dname      | ename  | sal     |
+------------+--------+---------+
| ACCOUNTING | CLARK  | 2450.00 |
| ACCOUNTING | KING   | 5000.00 |
| ACCOUNTING | MILLER | 1300.00 |
+------------+--------+---------+
3 rows in set (0.00 sec)

显示各个员工的姓名,工资,及工资级别

mysql> select emp.ename, emp.sal, salgrade.grade, salgrade.losal,salgrade.hisal from emp,salgrade where emp.sal between salgrade.losal and salgrade.hisal;
+--------+---------+-------+-------+-------+
| ename  | sal     | grade | losal | hisal |
+--------+---------+-------+-------+-------+
| SMITH  |  800.00 |     1 |   700 |  1200 |
| ALLEN  | 1600.00 |     3 |  1401 |  2000 |
| WARD   | 1250.00 |     2 |  1201 |  1400 |
| JONES  | 2975.00 |     4 |  2001 |  3000 |
| MARTIN | 1250.00 |     2 |  1201 |  1400 |
| BLAKE  | 2850.00 |     4 |  2001 |  3000 |
| CLARK  | 2450.00 |     4 |  2001 |  3000 |
| SCOTT  | 3000.00 |     4 |  2001 |  3000 |
| KING   | 5000.00 |     5 |  3001 |  9999 |
| TURNER | 1500.00 |     3 |  1401 |  2000 |
| ADAMS  | 1100.00 |     1 |   700 |  1200 |
| JAMES  |  950.00 |     1 |   700 |  1200 |
| FORD   | 3000.00 |     4 |  2001 |  3000 |
| MILLER | 1300.00 |     2 |  1201 |  1400 |
+--------+---------+-------+-------+-------+
14 rows in set (0.00 sec)

3. 自连接

自连接是指在同一张表连接查询
案例:
使用的子查询:
显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号--empno)

mysql> select * from emp where empno = (select mgr from emp where ename = 'FORD');
+--------+-------+---------+------+---------------------+---------+------+--------+
| empno  | ename | job     | mgr  | hiredate            | sal     | comm | deptno |
+--------+-------+---------+------+---------------------+---------+------+--------+
| 007566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL |     20 |
+--------+-------+---------+------+---------------------+---------+------+--------+
1 row in set (0.00 sec)

使用多表查询(自查询)

-- 使用到表的别名
--from emp leader, emp worker,给自己的表起别名,因为要先做笛卡尔积,所以别名可以先识别

mysql> select leader.empno,leader.ename from emp leader, emp worker where leader.empno = worker.mgr and worker.ename='FORD';
+--------+-------+
| empno  | ename |
+--------+-------+
| 007566 | JONES |
+--------+-------+
1 row in set (0.00 sec)
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
15天前
|
关系型数据库 MySQL
mysql关联查询
mysql关联查询
18 0
|
11天前
|
SQL 关系型数据库 MySQL
MySQL数据库—DQL查询语句(一篇教会你快速找到想要的数据)
MySQL数据库—DQL查询语句(一篇教会你快速找到想要的数据)
|
16天前
|
关系型数据库 MySQL 分布式数据库
PolarDB产品使用问题之mysql迁移后查询不走索引了,该如何解决
PolarDB产品使用合集涵盖了从创建与管理、数据管理、性能优化与诊断、安全与合规到生态与集成、运维与支持等全方位的功能和服务,旨在帮助企业轻松构建高可用、高性能且易于管理的数据库环境,满足不同业务场景的需求。用户可以通过阿里云控制台、API、SDK等方式便捷地使用这些功能,实现数据库的高效运维与持续优化。
|
8天前
|
SQL 关系型数据库 MySQL
Navicate,数据库,Mysql,改表,4月29日Finished - Unsuccessfully,导出数据不妨,右键,备份一下Mysql数据库的内容,你想导入和导出数据不如,用查询的方式去做
Navicate,数据库,Mysql,改表,4月29日Finished - Unsuccessfully,导出数据不妨,右键,备份一下Mysql数据库的内容,你想导入和导出数据不如,用查询的方式去做
|
10天前
|
存储 关系型数据库 MySQL
【Elasticsearch】在es中实现mysql中的FIND_IN_SET查询条件
【Elasticsearch】在es中实现mysql中的FIND_IN_SET查询条件
16 0
|
11天前
|
存储 关系型数据库 MySQL
MySQL数据库—多表设计与关联查询
MySQL数据库—多表设计与关联查询
|
11天前
|
关系型数据库 MySQL 数据库
MySQL数据库—查询:关联查询(一篇教会你在多表关联下查询数据)
MySQL数据库—查询:关联查询(一篇教会你在多表关联下查询数据)
|
14天前
|
关系型数据库 MySQL
mysql查询结果时间戳转成日期格式——date、DATE_FORMAT和FROM_UNIXTIME的使用
mysql查询结果时间戳转成日期格式——date、DATE_FORMAT和FROM_UNIXTIME的使用
15 0
|
15天前
|
存储 关系型数据库 MySQL
深入探索MySQL:成本模型解析与查询性能优化
深入探索MySQL:成本模型解析与查询性能优化
|
16天前
|
关系型数据库 MySQL 数据库
MySQL SELECT查询实战:练习题精选,提升你的数据库查询技能
MySQL SELECT查询实战:练习题精选,提升你的数据库查询技能