MySQL -复合查询

目录

一、先回顾:单表查询的基础操作(以EMP表为例)

1. 带条件的筛选

2. 排序与计算字段

(1)按部门号升序、工资降序排列

(2)计算年薪(工资 ×12 + 奖金,奖金为空则按 0 算)并排序

3. 聚合与分组查询

(1)查每个部门的平均工资、最高工资

(2)筛选平均工资 < 2000的部门

二、多表查询:跨表关联数据

DEPT部门表

SALGRADE工资级别表

1. 基础多表联查(等值连接)

(1)查 “员工名、工资、所属部门名”

(2)限定部门号为 10的员工

2. 三表联查(含工资级别表)

三、自连接:同一张表查上下级

四、子查询:用查询结果当条件 / 临时表

1. 单行子查询(返回一条结果)

2. 多行子查询(返回多条结果)

(1)查 “和 10 号部门岗位相同、但不属于 10 号部门” 的员工

(2)查 “工资比 30 号部门所有员工都高” 的员工

3. from 子句子查询(把子查询当临时表)

五、合并查询:union/union all

1. union(自动去重)

2. union all(保留重复)

写在最后


在实际开发中,仅用单表查询显然无法满足复杂业务需求。今天我们就以经典的员工管理系统(EMP员工表、DEPT部门表、SALGRADE工资级别表)为例,聊聊 MySQL 复合查询的核心玩法 —— 从单表查询到多表联查、子查询,再到合并查询,每一步都附上真实查询结果,帮你直观理解。

一、先回顾:单表查询的基础操作(以EMP表为例)

先明确EMP表基础数据(对应图片中表内容):

empnoenamejobmgrhiredatesalcommdeptno
7369SMITHCLERK79021980-12-17800NULL20
7499ALLENSALESMAN76981981-02-20160030030
7521WARDSALESMAN76981981-02-22125050030
7566JONESMANAGER78391981-04-022975NULL20
7654MARTINSALESMAN76981981-09-281250140030
7698BLAKEMANAGER78391981-05-012850NULL30
7782CLARKMANAGER78391981-06-092450NULL10
7788SCOTTANALYST75661987-04-193000NULL20
7839KINGPRESIDENTNULL1981-11-175000NULL10
7844TURNERSALESMAN76981981-09-081500030
7876ADAMSCLERK77881987-05-231100NULL20
7900JAMESCLERK76981981-12-03950NULL30
7902FORDANALYST75661981-12-033000NULL20
7934MILLERCLERK77821982-01-231300NULL10

1. 带条件的筛选

SELECT * FROM EMP 
WHERE (sal>500 OR job='MANAGER') 
AND ename LIKE 'J%';

查询结果

empnoenamejobmgrhiredatesalcommdeptno
7566JONESMANAGER78391981-04-022975NULL20
7900JAMESCLERK76981981-12-03950NULL30

2. 排序与计算字段

(1)按部门号升序、工资降序排列
SELECT * FROM EMP 
ORDER BY deptno, sal DESC;

查询结果(节选核心字段):

empnoenamesaldeptno
7839KING500010
7782CLARK245010
7934MILLER130010
7788SCOTT300020
7902FORD300020
7566JONES297520
7876ADAMS110020
7369SMITH80020
7698BLAKE285030
7499ALLEN160030
7844TURNER150030
7521WARD125030
7654MARTIN125030
7900JAMES95030
(2)计算年薪(工资 ×12 + 奖金,奖金为空则按 0 算)并排序
SELECT ename, sal*12+IFNULL(comm,0) AS '年薪' 
FROM EMP 
ORDER BY 年薪 DESC;

查询结果

ename年薪
KING60000
SCOTT36000
FORD36000
JONES35700
BLAKE34200
CLARK29400
ALLEN19500
TURNER18000
MARTIN16400
MILLER15600
WARD15500
ADAMS13200
JAMES11400
SMITH9600

3. 聚合与分组查询

(1)查每个部门的平均工资、最高工资
SELECT deptno, FORMAT(AVG(sal),2) AS avg_sal, MAX(sal) AS max_sal 
FROM EMP 
GROUP BY deptno;

查询结果

deptnoavg_salmax_sal
102,916.675000
202,175.003000
301,566.672850
(2)筛选平均工资 < 2000的部门
SELECT deptno, AVG(sal) AS avg_sal 
FROM EMP 
GROUP BY deptno 
HAVING avg_sal<2000;

查询结果

deptnoavg_sal
301566.6667

二、多表查询:跨表关联数据

先明确关联表基础数据:

DEPT部门表

deptnodnameloc
10ACCOUNTINGNEW YORK
20RESEARCHDALLAS
30SALESCHICAGO
40OPERATIONSBOSTON

SALGRADE工资级别表

gradelosalhisal
17001200
212011400
314012000
420013000
530019999

1. 基础多表联查(等值连接)

(1)查 “员工名、工资、所属部门名”
SELECT EMP.ename, EMP.sal, DEPT.dname 
FROM EMP, DEPT 
WHERE EMP.deptno = DEPT.deptno;

查询结果(节选):

enamesaldname
SMITH800RESEARCH
ALLEN1600SALES
WARD1250SALES
JONES2975RESEARCH
MARTIN1250SALES
BLAKE2850SALES
CLARK2450ACCOUNTING
SCOTT3000RESEARCH
KING5000ACCOUNTING
TURNER1500SALES
ADAMS1100RESEARCH
JAMES950SALES
FORD3000RESEARCH
MILLER1300ACCOUNTING
(2)限定部门号为 10的员工
SELECT ename, sal, dname 
FROM EMP, DEPT 
WHERE EMP.deptno=DEPT.deptno 
AND DEPT.deptno=10;

查询结果

enamesaldname
CLARK2450ACCOUNTING
KING5000ACCOUNTING
MILLER1300ACCOUNTING

2. 三表联查(含工资级别表)

SELECT ename, sal, grade 
FROM EMP, SALGRADE 
WHERE EMP.sal BETWEEN losal AND hisal;

查询结果

enamesalgrade
SMITH8001
ALLEN16003
WARD12502
JONES29754
MARTIN12502
BLAKE28504
CLARK24504
SCOTT30004
KING50005
TURNER15003
ADAMS11001
JAMES9501
FORD30004
MILLER13002

三、自连接:同一张表查上下级

-- 别名leader代表领导,worker代表员工
SELECT leader.empno, leader.ename 
FROM emp leader, emp worker 
WHERE leader.empno = worker.mgr 
AND worker.ename='FORD';

查询结果

empnoename
7566JONES

四、子查询:用查询结果当条件 / 临时表

1. 单行子查询(返回一条结果)

SELECT ename, job 
FROM EMP 
WHERE sal = (SELECT MAX(sal) FROM EMP);

查询结果

enamejob
KINGPRESIDENT

2. 多行子查询(返回多条结果)

(1)查 “和 10 号部门岗位相同、但不属于 10 号部门” 的员工
SELECT ename,job,sal,deptno 
FROM emp 
WHERE job IN (SELECT DISTINCT job FROM emp WHERE deptno=10) 
AND deptno<>10;

查询结果

enamejobsaldeptno
JONESMANAGER297520
BLAKEMANAGER285030
SMITHCLERK80020
ADAMSCLERK110020
JAMESCLERK95030
(2)查 “工资比 30 号部门所有员工都高” 的员工
SELECT ename, sal, deptno 
FROM EMP 
WHERE sal > ALL(SELECT sal FROM EMP WHERE deptno=30);

查询结果

enamesaldeptno
JONES297520
SCOTT300020
KING500010
FORD300020

3. from 子句子查询(把子查询当临时表)

-- 先查各部门平均工资(临时表tmp),再关联员工表
SELECT ename, deptno, sal, FORMAT(tmp.avg_sal,2) AS dept_avg_sal
FROM EMP, 
(SELECT AVG(sal) avg_sal, deptno dt FROM EMP GROUP BY deptno) tmp
WHERE EMP.sal > tmp.avg_sal 
AND EMP.deptno=tmp.dt;

查询结果

enamedeptnosaldept_avg_sal
KING1050002,916.67
JONES2029752,175.00
SCOTT2030002,175.00
FORD2030002,175.00
BLAKE3028501,566.67
ALLEN3016001,566.67

五、合并查询:union/union all

1. union(自动去重)

SELECT ename, sal, job FROM EMP WHERE sal>2500 
UNION
SELECT ename, sal, job FROM EMP WHERE job='MANAGER';

查询结果(无重复数据):

enamesaljob
JONES2975MANAGER
BLAKE2850MANAGER
SCOTT3000ANALYST
KING5000PRESIDENT
FORD3000ANALYST
CLARK2450MANAGER

2. union all(保留重复)

SELECT ename, sal, job FROM EMP WHERE sal>2500 
UNION ALL
SELECT ename, sal, job FROM EMP WHERE job='MANAGER';

查询结果(JONES、BLAKE 重复出现):

enamesaljob
JONES2975MANAGER
BLAKE2850MANAGER
SCOTT3000ANALYST
KING5000PRESIDENT
FORD3000ANALYST
JONES2975MANAGER
BLAKE2850MANAGER
CLARK2450MANAGER

写在最后

MySQL 复合查询是实际开发的核心技能,核心是理清表关系、灵活组合单表 / 多表 / 子查询语法。本文所有示例均基于真实员工管理表数据,查询结果可直接验证,建议你复制 SQL 语句在本地数据库中实操,更快掌握各类查询技巧~

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值