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 语句在本地数据库中实操,更快掌握各类查询技巧~

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

相关文章

  • Linux下自动备份MySQL的方法

    Linux下自动备份MySQL的方法

    这篇文章主要介绍了Linux下自动备份MySQL的方法,需要的朋友可以参考下
    2015-01-01
  • MySQL sql_mode的使用详解

    MySQL sql_mode的使用详解

    这篇文章主要介绍了MySQL sql_mode的使用详解,帮助大家更好的理解和学习使用MySQL数据库,感兴趣的朋友可以了解下
    2021-05-05
  • mysql数据库锁的产生原因及解决办法

    mysql数据库锁的产生原因及解决办法

    这篇文章主要介绍了mysql数据库锁的产生原因及解决办法,需要的朋友可以参考下
    2016-01-01
  • mysql多行子查询实战案例(只包含不相关子查询)

    mysql多行子查询实战案例(只包含不相关子查询)

    在MySQL中多行子查询(也称为 IN 子查询)是指子查询返回多行数据,并且这些数据用于主查询中的某个条件判断,这篇文章主要介绍了mysql多行子查询(只包含不相关子查询)的相关资料,需要的朋友可以参考下
    2024-10-10
  • mysql清空表数据的两种方式和区别解析

    mysql清空表数据的两种方式和区别解析

    这篇文章主要介绍了mysql清空表数据的两种方式和区别,本文通过文字实例代码相结合给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-05-05
  • MySQL用户账户管理和权限管理深入讲解

    MySQL用户账户管理和权限管理深入讲解

    这篇文章主要给大家介绍了关于MySQL用户账户管理和权限管理的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-12-12
  • MySQL 不等于的三种使用及区别

    MySQL 不等于的三种使用及区别

    MySQL中常用到判断符号,而不等于是比较常用的符号,不等于主要是三种,本文主要介绍了三种的使用及区别,感兴趣的同学可以了解一下
    2021-06-06
  • mysql批量删除大量数据

    mysql批量删除大量数据

    这篇文章主要介绍了mysql批量删除大量数据的相关资料,需要的朋友可以参考下
    2017-04-04
  • MySQL的主从复制步骤详解及常见错误解决方法

    MySQL的主从复制步骤详解及常见错误解决方法

    这篇文章主要介绍了MySQL的主从复制步骤详解及常见错误解决方法,文中主张同步时跳过临时错误,并对Slave_IO_Running: No错误的解决给出了方案,需要的朋友可以参考下
    2016-02-02
  • MySQL数据延迟跳动的问题解决

    MySQL数据延迟跳动的问题解决

    这篇文章主要介绍了MySQL数据延迟跳动的问题如何解决,帮助大家更好的理解和学习MySQL,感兴趣的朋友可以了解下
    2020-08-08

最新评论