MySQL -复合查询

目录

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

[1. 带条件的筛选](#1. 带条件的筛选)

[2. 排序与计算字段](#2. 排序与计算字段)

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

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

[3. 聚合与分组查询](#3. 聚合与分组查询)

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

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

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

DEPT部门表

SALGRADE工资级别表

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

[(1)查 "员工名、工资、所属部门名"](#(1)查 “员工名、工资、所属部门名”)

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

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

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

[四、子查询:用查询结果当条件 / 临时表](#四、子查询:用查询结果当条件 / 临时表)

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

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

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

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

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

[五、合并查询:union/union all](#五、合并查询:union/union all)

[1. union(自动去重)](#1. union(自动去重))

[2. union all(保留重复)](#2. union all(保留重复))

写在最后


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

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

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

empno ename job mgr hiredate sal comm deptno
7369 SMITH CLERK 7902 1980-12-17 800 NULL 20
7499 ALLEN SALESMAN 7698 1981-02-20 1600 300 30
7521 WARD SALESMAN 7698 1981-02-22 1250 500 30
7566 JONES MANAGER 7839 1981-04-02 2975 NULL 20
7654 MARTIN SALESMAN 7698 1981-09-28 1250 1400 30
7698 BLAKE MANAGER 7839 1981-05-01 2850 NULL 30
7782 CLARK MANAGER 7839 1981-06-09 2450 NULL 10
7788 SCOTT ANALYST 7566 1987-04-19 3000 NULL 20
7839 KING PRESIDENT NULL 1981-11-17 5000 NULL 10
7844 TURNER SALESMAN 7698 1981-09-08 1500 0 30
7876 ADAMS CLERK 7788 1987-05-23 1100 NULL 20
7900 JAMES CLERK 7698 1981-12-03 950 NULL 30
7902 FORD ANALYST 7566 1981-12-03 3000 NULL 20
7934 MILLER CLERK 7782 1982-01-23 1300 NULL 10

1. 带条件的筛选

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

查询结果

empno ename job mgr hiredate sal comm deptno
7566 JONES MANAGER 7839 1981-04-02 2975 NULL 20
7900 JAMES CLERK 7698 1981-12-03 950 NULL 30

2. 排序与计算字段

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

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

empno ename sal deptno
7839 KING 5000 10
7782 CLARK 2450 10
7934 MILLER 1300 10
7788 SCOTT 3000 20
7902 FORD 3000 20
7566 JONES 2975 20
7876 ADAMS 1100 20
7369 SMITH 800 20
7698 BLAKE 2850 30
7499 ALLEN 1600 30
7844 TURNER 1500 30
7521 WARD 1250 30
7654 MARTIN 1250 30
7900 JAMES 950 30
(2)计算年薪(工资 ×12 + 奖金,奖金为空则按 0 算)并排序
sql 复制代码
SELECT ename, sal*12+IFNULL(comm,0) AS '年薪' 
FROM EMP 
ORDER BY 年薪 DESC;

查询结果

ename 年薪
KING 60000
SCOTT 36000
FORD 36000
JONES 35700
BLAKE 34200
CLARK 29400
ALLEN 19500
TURNER 18000
MARTIN 16400
MILLER 15600
WARD 15500
ADAMS 13200
JAMES 11400
SMITH 9600

3. 聚合与分组查询

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

查询结果

deptno avg_sal max_sal
10 2,916.67 5000
20 2,175.00 3000
30 1,566.67 2850
(2)筛选平均工资 < 2000的部门
sql 复制代码
SELECT deptno, AVG(sal) AS avg_sal 
FROM EMP 
GROUP BY deptno 
HAVING avg_sal<2000;

查询结果

deptno avg_sal
30 1566.6667

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

先明确关联表基础数据:

DEPT部门表

deptno dname loc
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON

SALGRADE工资级别表

grade losal hisal
1 700 1200
2 1201 1400
3 1401 2000
4 2001 3000
5 3001 9999

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

(1)查 "员工名、工资、所属部门名"
sql 复制代码
SELECT EMP.ename, EMP.sal, DEPT.dname 
FROM EMP, DEPT 
WHERE EMP.deptno = DEPT.deptno;

查询结果(节选):

ename sal dname
SMITH 800 RESEARCH
ALLEN 1600 SALES
WARD 1250 SALES
JONES 2975 RESEARCH
MARTIN 1250 SALES
BLAKE 2850 SALES
CLARK 2450 ACCOUNTING
SCOTT 3000 RESEARCH
KING 5000 ACCOUNTING
TURNER 1500 SALES
ADAMS 1100 RESEARCH
JAMES 950 SALES
FORD 3000 RESEARCH
MILLER 1300 ACCOUNTING
(2)限定部门号为 10的员工
sql 复制代码
SELECT ename, sal, dname 
FROM EMP, DEPT 
WHERE EMP.deptno=DEPT.deptno 
AND DEPT.deptno=10;

查询结果

ename sal dname
CLARK 2450 ACCOUNTING
KING 5000 ACCOUNTING
MILLER 1300 ACCOUNTING

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

sql 复制代码
SELECT ename, sal, grade 
FROM EMP, SALGRADE 
WHERE EMP.sal BETWEEN losal AND hisal;

查询结果

ename sal grade
SMITH 800 1
ALLEN 1600 3
WARD 1250 2
JONES 2975 4
MARTIN 1250 2
BLAKE 2850 4
CLARK 2450 4
SCOTT 3000 4
KING 5000 5
TURNER 1500 3
ADAMS 1100 1
JAMES 950 1
FORD 3000 4
MILLER 1300 2

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

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

查询结果

empno ename
7566 JONES

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

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

sql 复制代码
SELECT ename, job 
FROM EMP 
WHERE sal = (SELECT MAX(sal) FROM EMP);

查询结果

ename job
KING PRESIDENT

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

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

查询结果

ename job sal deptno
JONES MANAGER 2975 20
BLAKE MANAGER 2850 30
SMITH CLERK 800 20
ADAMS CLERK 1100 20
JAMES CLERK 950 30
(2)查 "工资比 30 号部门所有员工都高" 的员工
sql 复制代码
SELECT ename, sal, deptno 
FROM EMP 
WHERE sal > ALL(SELECT sal FROM EMP WHERE deptno=30);

查询结果

ename sal deptno
JONES 2975 20
SCOTT 3000 20
KING 5000 10
FORD 3000 20

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

sql 复制代码
-- 先查各部门平均工资(临时表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;

查询结果

ename deptno sal dept_avg_sal
KING 10 5000 2,916.67
JONES 20 2975 2,175.00
SCOTT 20 3000 2,175.00
FORD 20 3000 2,175.00
BLAKE 30 2850 1,566.67
ALLEN 30 1600 1,566.67

五、合并查询:union/union all

1. union(自动去重)

sql 复制代码
SELECT ename, sal, job FROM EMP WHERE sal>2500 
UNION
SELECT ename, sal, job FROM EMP WHERE job='MANAGER';

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

ename sal job
JONES 2975 MANAGER
BLAKE 2850 MANAGER
SCOTT 3000 ANALYST
KING 5000 PRESIDENT
FORD 3000 ANALYST
CLARK 2450 MANAGER

2. union all(保留重复)

sql 复制代码
SELECT ename, sal, job FROM EMP WHERE sal>2500 
UNION ALL
SELECT ename, sal, job FROM EMP WHERE job='MANAGER';

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

ename sal job
JONES 2975 MANAGER
BLAKE 2850 MANAGER
SCOTT 3000 ANALYST
KING 5000 PRESIDENT
FORD 3000 ANALYST
JONES 2975 MANAGER
BLAKE 2850 MANAGER
CLARK 2450 MANAGER

写在最后

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

相关推荐
鸿蒙开发工程师—阿辉2 小时前
HarmonyOS 5 数据持久化:关系型数据库 (RelationalStore)
jvm·数据库·harmonyos
合方圆~小文2 小时前
双目摄像头在不同距离精度差异
数据库·人工智能·模块测试
源代码•宸2 小时前
goframe框架签到系统项目开发(分布式 ID 生成器、雪花算法、抽离业务逻辑到service层)
经验分享·分布式·mysql·算法·golang·雪花算法·goframe
计算机毕设VX:Fegn08952 小时前
计算机毕业设计|基于springboot + vue校园招聘系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
航Hang*2 小时前
第3章:复习篇——第3节:数据查询与统计
数据库·笔记·sql·mysql
DBA小马哥2 小时前
金仓数据库:构建国产数据库安全迁移新范式,助力Oracle替代进程
数据库·oracle
only°夏至besos2 小时前
基于 Dinky + FlinkSQL + Flink CDC 同步 MySQL 数据到 Elasticsearch、Kafka
mysql·elasticsearch·flink
星环科技2 小时前
什么是分布式数据库?一文了解分布式数据库
数据库
么么...2 小时前
SQL 学习指南:从零开始掌握DQL结构化查询语言
数据库·经验分享·笔记·sql