当前位置: 首页 > news >正文

08.MySQL复合查询详解

08.MySQL复合查询详解

基本查询回顾

多表查询

自连接

子查询

单行子查询

多行子查询

多列子查询

在FROM子句中使用子查询

合并查询


MySQL复合查询详解

基本查询回顾

在正式进入复合查询之前,先简单回顾一下MySQL的基本查询操作。假设我们有三张表:员工表(emp)、部门表(dept)和工资等级表(salgrade)。这些表的结构和数据如下:

员工表(emp

empnoenamejobmgrhiredatesalcommdeptno
7369SMITHCLERK79021980-12-17800NULL20
7499ALLENSALESMAN76981981-02-20160030030

部门表(dept

deptnodnameloc
10ACCOUNTINGNEW YORK
20RESEARCHDALLAS

工资等级表(salgrade

gradelosalhisal
17001200
212011400

基本查询通常围绕单张表展开,比如筛选特定条件的记录、排序、分组统计等。例如:

  • 查询工资高于500或岗位为MANAGER的员工,并且要求姓名首字母为大写J
    SELECT ename, sal, job 
    FROM emp 
    WHERE (sal > 500 OR job = 'MANAGER') AND ename LIKE 'J%';
    
  • 按部门号升序、工资降序显示员工信息:
    SELECT ename, deptno, sal 
    FROM emp 
    ORDER BY deptno ASC, sal DESC;
    
  • 查询年薪最高的员工:
    SELECT ename, sal*12 + IFNULL(comm, 0) AS annual_salary 
    FROM emp 
    ORDER BY annual_salary DESC 
    LIMIT 1;
    

这些基础查询为后续的复合查询奠定了基础。接下来我们将深入探讨多表关联、自连接、子查询等高级查询技巧。


多表查询

为什么需要多表查询?

现实中的数据往往分散在多个表中。例如,员工信息存储在emp表中,部门信息存储在dept表中,而工资等级信息则在salsgrade表中。如果需要查询某个员工的部门名称或工资等级,就必须将这些表关联起来。

笛卡尔积:多表查询的起点

多表查询的本质是对多张表取笛卡尔积,即所有记录的组合。例如:

SELECT * FROM emp, dept;

这条语句会返回emp表和dept表的笛卡尔积,结果中每一行都是emp的一条记录与dept的一条记录的组合。然而,这种组合大多是无意义的,因此需要通过WHERE子句过滤出有效数据。

笛卡尔积的初步过滤

以查询部门号为10的员工信息为例:

SELECT d.dname, e.ename, e.sal 
FROM emp e, dept d 
WHERE e.deptno = d.deptno AND e.deptno = 10;

这里的关键是e.deptno = d.deptno,它确保了只有员工所在部门与部门表中的记录匹配时才会被选中。

经典案例:查询员工的工资等级

要显示每个员工的姓名、工资和对应的工资等级,需要关联empsalsgrade表:

SELECT e.ename, e.sal, s.grade 
FROM emp e, salgrade s 
WHERE e.sal BETWEEN s.losal AND s.hisal;

这里的BETWEEN条件确保工资落在某个等级的范围内。


自连接

什么是自连接?

自连接是指同一张表与自身进行关联查询。例如,员工表中的mgr字段表示上级领导的编号,而领导本身也是员工,因此可以通过自连接查询员工的领导信息。

案例:查询员工FORD的上级领导

SELECT e1.ename AS employee, e2.ename AS manager 
FROM emp e1, emp e2 
WHERE e1.mgr = e2.empno AND e1.ename = 'FORD';

这里通过给emp表起两个别名e1e2,分别代表员工和领导。e1.mgr = e2.empno确保员工的领导编号与领导的员工编号匹配。


子查询

子查询是嵌套在其他SQL语句中的查询,常用于动态获取条件值。子查询可分为单行子查询、多行子查询、多列子查询等。

单行子查询

单行子查询返回单个值。例如,查询SMITH所在部门的其他员工:

SELECT ename, job, sal, deptno 
FROM emp 
WHERE deptno = (SELECT deptno FROM emp WHERE ename = 'SMITH') AND ename != 'SMITH';

子查询(SELECT deptno FROM emp WHERE ename = 'SMITH')先获取SMITH的部门号,然后外层查询筛选出同一部门的其他员工。

多行子查询

多行子查询返回多行单列数据,常与INALLANY等关键字配合使用。

使用IN筛选多行结果

查询与10号部门岗位相同的员工(不包括10号部门本身):

SELECT ename, job, sal, deptno 
FROM emp 
WHERE job IN (SELECT DISTINCT job FROM emp WHERE deptno = 10) AND deptno != 10;

子查询SELECT DISTINCT job FROM emp WHERE deptno = 10先获取10号部门的所有岗位,外层查询通过IN筛选出这些岗位的员工。

使用ALLANY比较多行结果
  • 查询工资高于30号部门所有员工的员工:
    SELECT ename, sal, deptno 
    FROM emp 
    WHERE sal > ALL(SELECT sal FROM emp WHERE deptno = 30);
    
  • 查询工资高于30号部门任意员工的员工:
    SELECT ename, sal, deptno 
    FROM emp 
    WHERE sal > ANY(SELECT sal FROM emp WHERE deptno = 30);
    

多列子查询

多列子查询返回多列数据,通常用于比较多个字段。例如,查询与SMITH部门和岗位完全相同的员工:

SELECT ename, deptno, job 
FROM emp 
WHERE (deptno, job) = (SELECT deptno, job FROM emp WHERE ename = 'SMITH') AND ename != 'SMITH';

在FROM子句中使用子查询

子查询不仅可以出现在WHERE子句中,还可以作为临时表嵌套在FROM子句中。例如,查询每个部门工资高于平均工资的员工:

SELECT e.ename, e.deptno, e.sal, tmp.avg_sal 
FROM emp e, 
(SELECT deptno, AVG(sal) AS avg_sal FROM emp GROUP BY deptno) tmp 
WHERE e.deptno = tmp.deptno AND e.sal > tmp.avg_sal;

这里子查询tmp先计算每个部门的平均工资,外层查询通过关联emptmp筛选出符合条件的员工。


合并查询

合并查询通过UNIONUNION ALL将多个查询结果合并。

UNIONUNION ALL的区别

  • UNION:合并结果并去重。
  • UNION ALL:合并结果但不去重。

案例:查询工资大于2500或职位为MANAGER的员工

SELECT * FROM emp WHERE sal > 2500 
UNION 
SELECT * FROM emp WHERE job = 'MANAGER';

等价于:

SELECT * FROM emp WHERE sal > 2500 OR job = 'MANAGER';

但使用UNION可以更清晰地拆分查询逻辑。


综合案例:查询每个部门的最高工资员工

方法一:子查询+多表查询

SELECT e.ename, e.deptno, e.sal, tmp.max_sal 
FROM emp e, 
(SELECT deptno, MAX(sal) AS max_sal FROM emp GROUP BY deptno) tmp 
WHERE e.deptno = tmp.deptno AND e.sal = tmp.max_sal;

方法二:自连接

SELECT e1.ename, e1.deptno, e1.sal 
FROM emp e1 
WHERE e1.sal = (SELECT MAX(sal) FROM emp e2 WHERE e1.deptno = e2.deptno);

总结

MySQL的复合查询功能强大,能够处理复杂的业务需求。通过多表关联、自连接、子查询和合并查询,开发者可以灵活地组合数据,实现跨表分析、动态筛选和结果聚合。掌握这些技巧后,即使是面对海量数据,也能高效地提取所需信息。

相关文章:

  • STM32与GD32标准外设库深度对比
  • SoloSpeech - 高质量语音处理模型,一键提取指定说话人音频并提升提取音频清晰度和质量 本地一键整合包下载
  • TypeScript 定义同步方法
  • HarmonyOS图片image使用
  • 80.在服务器部署LLAVA模型
  • 【Doris基础】Apache Doris中的Fragment概念详解
  • Agno:使用简单代码构建AI智能体
  • JS语法笔记
  • 风云二号G星:我国气象监测的“天眼”
  • 小巧实用,Windows文件夹着色软件推荐
  • MySQL强化关键_019_索引优化
  • [Linux] MySQL源码编译安装
  • MySQL计算精度计算加减乘除取模方式和方法总计
  • 2025年06月03日Github流行趋势
  • 【散刷】二叉树基础OJ题(二)
  • 【学习记录】深入解析 AI 交互中的五大核心概念:Prompt、Agent、MCP、Function Calling 与 Tools
  • Linux: network : switch:hp5500
  • 电阻电容的选型
  • 低谷才是出成绩
  • JVM—垃圾收集算法和HotSpot算法实现细节
  • 杭州网站建设制作联系电话/百度指数查询工具
  • 网站建设书/网络营销推广微信hyhyk1效果好
  • 利用vs做网站/网站建设7个基本流程
  • 西安分销商城网站建设/网络营销个人感悟小结
  • 定州国际陆港项目/重庆seo团队
  • 石景山网站建设的大公司/百度搜索排名推广