MySQL中的复合查询使用解读

 更新时间:2025年12月26日 08:41:04   作者:前似锦  
本文详细介绍了MySQL复合查询的核心玩法,包括单表查询、多表联查、子查询和合并查询,通过实际的员工管理系统数据,展示了如何使用各种查询语句来满足复杂的业务需求

在实际开发中,仅用单表查询显然无法满足复杂业务需求。今天我们就以经典的员工管理系统(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 语句在本地数据库中实操,更快掌握各类查询技巧~

这些仅为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • MySQL中的CONCAT()函数:轻松拼接字符串的利器

    MySQL中的CONCAT()函数:轻松拼接字符串的利器

    这篇文章主要介绍了MySQL中的CONCAT()函数:轻松拼接字符串的利器,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • 解决windows下mysql8修改my.ini设置datadir后无法启动问题

    解决windows下mysql8修改my.ini设置datadir后无法启动问题

    在修改MySQL的my.ini文件以更改数据目录后,可能会遇到无法启动的问题,这通常是因为字符编码被改变或新路径权限不足,正确的做法是备份my.ini文件,确保使用ANSI字符编码修改datadir,并确保新路径有足够的权限,特别是SYSTEM或NETWORKSERVICE权限
    2025-01-01
  • MySQL8中的存储引擎以及文件解析

    MySQL8中的存储引擎以及文件解析

    这篇文章主要介绍了MySQL8中的存储引擎以及文件使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • 详解一条sql语句在mysql中是如何执行的

    详解一条sql语句在mysql中是如何执行的

    这篇文章主要介绍了一条sql语句在mysql中是如何执行的,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • 关闭和打开本地的mysql实现方式

    关闭和打开本地的mysql实现方式

    这篇文章主要介绍了关闭和打开本地的mysql实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-05-05
  • MySQL数据库误删恢复的超详细教程

    MySQL数据库误删恢复的超详细教程

    MySQL误删数据库,造成了数据的丢失,这是非常尴尬的,但是有许多方案可以用来尝试恢复丢失的数据库,这篇文章主要给大家介绍了关于MySQL数据库误删恢复的超详细教程,需要的朋友可以参考下
    2024-03-03
  • MySQL实战之Insert语句的使用心得

    MySQL实战之Insert语句的使用心得

    这篇文章主要给大家介绍了关于MySQL实战之Insert语句的使用心得的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • 解决mysql服务器在无操作超时主动断开连接的情况

    解决mysql服务器在无操作超时主动断开连接的情况

    这篇文章主要介绍了解决mysql服务器在无操作超时主动断开连接的情况,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • SQL行转列与列转行详情

    SQL行转列与列转行详情

    这篇文章主要介绍了SQL行转列与列转行,违章以SQL数据展开详细内容,具有一定的参考价值,需要的小伙伴可以参考一下,希望对你有所帮助
    2022-03-03
  • MYSQL批量UPDATE的两种方式小结

    MYSQL批量UPDATE的两种方式小结

    本文主要介绍了MYSQL批量UPDATE的两种方式小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-03-03

最新评论