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

MySQL 子查询(多行)

MySQL 子查询(多行)

MySQL 子查询(多行)学习笔记


一、子查询基础概念

子查询(也叫内查询)是嵌套在 SELECTFROMWHEREHAVING 等语句中的查询,用于分步完成复杂筛选。

  • 按返回结果分为:单行子查询(返回1行)、多行子查询(返回多行)
  • 按执行方式分为:非相关子查询(独立执行)、相关子查询(依赖外层查询)

二、多行子查询与比较运算符

1. 多行比较运算符说明

运算符 含义 使用场景
IN 等于列表中的任意一个值 匹配子查询结果中存在的值
ANY 与子查询返回的某一个值比较 需配合 > < = 等比较符
ALL 与子查询返回的所有值比较 需配合 > < = 等比较符
SOME ANY 的别名,作用完全相同 不常用,一般用 ANY

2. 多行子查询示例

示例1:查询各部门最低工资的员工

-- 子查询:先查出每个部门的最低工资(多行结果)
-- 外层查询:匹配工资在这些最低工资列表中的员工
SELECT employee_id, last_name
FROM employees
WHERE salary IN (SELECT MIN(salary)FROM employeesGROUP BY department_id
);

示例2:ANY 运算符示例

需求:返回非 IT_PROG 岗位中,工资比 IT_PROG 任一员工低的员工信息

-- 子查询:先查出所有 IT_PROG 岗位的工资列表
-- 外层查询:筛选工资 < 列表中任意一个值(即比最低工资低)
SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE job_id <> 'IT_PROG'
AND salary < ANY (SELECT salaryFROM employeesWHERE job_id = 'IT_PROG'
);

说明:salary < ANY (...) 等价于 salary < 列表中的最大值,只要比列表中任意一个值小就满足条件。

示例3:ALL 运算符示例

需求:返回非 IT_PROG 岗位中,工资比所有 IT_PROG 员工都低的员工信息

-- 子查询:先查出所有 IT_PROG 岗位的工资列表
-- 外层查询:筛选工资 < 列表中所有值(即比最低工资还低)
SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE job_id <> 'IT_PROG'
AND salary < ALL (SELECT salaryFROM employeesWHERE job_id = 'IT_PROG'
);

说明:salary < ALL (...) 等价于 salary < 列表中的最小值,必须比列表中所有值都小才满足条件。


三、聚合函数嵌套问题

1. 错误示例:聚合函数不能直接嵌套

-- ❌ 错误写法:MySQL 不支持聚合函数直接嵌套
SELECT MIN(AVG(salary))
FROM employees
GROUP BY department_id;

错误原因:MySQL 中聚合函数不能直接嵌套使用,需要通过子查询实现。

2. 正确实现:查询平均工资最低的部门ID

方式1:子查询 + 临时表

-- 第一步:先查询每个部门的平均工资,作为临时表
-- 第二步:在临时表中取最小平均工资
-- 第三步:筛选平均工资等于最小值的部门
SELECT department_id
FROM employees
GROUP BY department_id
HAVING AVG(salary) = (SELECT MIN(avg_sal)FROM (SELECT AVG(salary) avg_salFROM employeesGROUP BY department_id) t_dept_avg_sal
);

方式2:ALL 运算符实现

-- 利用 ALL 运算符,筛选平均工资 <= 所有部门平均工资的部门(即最小值)
SELECT department_id
FROM employees
GROUP BY department_id
HAVING AVG(salary) <= ALL (SELECT AVG(salary) avg_salFROM employeesGROUP BY department_id
);

四、子查询中的空值问题

问题示例:NOT IN 与子查询空值陷阱

-- ❌ 问题写法:子查询返回包含 NULL 的列表时,NOT IN 结果为空
SELECT last_name
FROM employees
WHERE employee_id NOT IN (SELECT manager_idFROM employees-- 缺少 WHERE manager_id IS NOT NULL,子查询结果包含 NULL
);

问题原因NOT IN (列表) 本质是 != 值1 AND != 值2 AND ...,如果列表中存在 NULL,则条件结果为 UNKNOWN,导致整个查询返回空。

正确写法:过滤子查询中的 NULL

-- ✅ 正确写法:在子查询中排除 NULL
SELECT last_name
FROM employees
WHERE employee_id NOT IN (SELECT manager_idFROM employeesWHERE manager_id IS NOT NULL
);

五、补充知识点

  1. ANYALL 的等价关系

    • salary > ANY (list)salary > MIN(list)
    • salary < ANY (list)salary < MAX(list)
    • salary > ALL (list)salary > MAX(list)
    • salary < ALL (list)salary < MIN(list)
  2. 子查询使用规范

    • 非相关子查询优先使用,可读性和性能更好;
    • IN 子查询中,子查询结果尽量避免 NULL;
    • 复杂嵌套子查询可拆分为临时表,提升可读性和性能。

六、完整代码汇总

-- 1. 各部门最低工资的员工
SELECT employee_id, last_name
FROM employees
WHERE salary IN (SELECT MIN(salary)FROM employeesGROUP BY department_id
);-- 2. ANY:比 IT_PROG 任一工资低的非 IT_PROG 员工
SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE job_id <> 'IT_PROG'
AND salary < ANY (SELECT salaryFROM employeesWHERE job_id = 'IT_PROG'
);-- 3. ALL:比 IT_PROG 所有工资都低的非 IT_PROG 员工
SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE job_id <> 'IT_PROG'
AND salary < ALL (SELECT salaryFROM employeesWHERE job_id = 'IT_PROG'
);-- 4. 平均工资最低的部门(方式1:子查询+临时表)
SELECT department_id
FROM employees
GROUP BY department_id
HAVING AVG(salary) = (SELECT MIN(avg_sal)FROM (SELECT AVG(salary) avg_salFROM employeesGROUP BY department_id) t_dept_avg_sal
);-- 5. 平均工资最低的部门(方式2:ALL运算符)
SELECT department_id
FROM employees
GROUP BY department_id
HAVING AVG(salary) <= ALL (SELECT AVG(salary) avg_salFROM employeesGROUP BY department_id
);-- 6. 无下属的员工(NOT IN 过滤 NULL)
SELECT last_name
FROM employees
WHERE employee_id NOT IN (SELECT manager_idFROM employeesWHERE manager_id IS NOT NULL
);
http://www.jsqmd.com/news/923557/

相关文章:

  • 年省18万增收50万:换热器哪家强案例解析 - 资讯纵览
  • AI时代内容生产力革命,深度拆解Google Gemini原生日历规划框架与企业落地适配方案
  • 鸣潮自动化工具ok-ww:5分钟快速上手指南,释放你的游戏时间
  • 2026年电线电缆厂家:解读三大核心发展趋势 - 资讯纵览
  • DIY低成本雷达测速车牌抓拍系统:350美元实现社区超速监控
  • Arduino电子秤实战:从ADC读取到map函数映射与系统校准
  • ABC460
  • Video2X完整指南:三步实现AI视频画质增强与帧率提升
  • 树莓派+ESP32构建乐高火车自动化控制系统:从传感器到调度逻辑
  • 换热器哪家强?2026换热器选购指南:掌握标准选对不踩坑 - 资讯纵览
  • 基于线性执行器的上肢辅助外骨骼DIY:从机电一体化到康复应用
  • 东莞东城装修公司哪家好?2026年最新实地考察报告 - liuminghui
  • 洛雪音乐音源终极指南:免费获取全网高品质无损音乐
  • 基于Arduino与Processing的超声波手势控制飞行游戏开发实战
  • 基于Arduino与超声波传感器的自动NERF哨戒炮DIY全解析
  • 如何用Sunshine搭建个人游戏串流服务器:从入门到精通的完整指南
  • 2026单宁酶深度选型指南:如何为食品加工匹配最佳方案? - 资讯纵览
  • WPinternals深度解析:如何解锁Windows Phone Bootloader实现设备重生
  • 【紧急预警】Gemini同类AI项目92%公关失败源于这1个被忽视的合规盲区
  • 镜像视界:以核心尖端技术,领跑全球视频孪生新赛道
  • 2026年空间吸声体厂家推荐排行榜:阵列声学障板、体育馆/篮球馆/岩棉/环保吸声体优质工厂! - 资讯纵览
  • 基于Arduino与步进电机的自动吉他弹奏器DIY全攻略
  • 如何用AzurLaneAutoScript实现碧蓝航线全自动管理:终极游戏助手指南
  • Python之strformat包语法、参数和实际应用案例
  • 2026年高压灯带深度选型指南:如何为你的空间匹配最佳方案? - 资讯纵览
  • FactoryBluePrints:解锁《戴森球计划》工厂设计艺术的终极蓝图库
  • 基于Arduino UNO的工业级条码扫描与EEPROM烧录器设计与实现
  • 废旧材料DIY巨型电阻模型:从电子原理到创客教育的实践指南
  • Ubuntu 20.04下搞定Cadence Virtuoso AMS仿真:从INCISIVE151安装到GCC版本避坑全记录
  • PC版微信QQ防撤回终极指南:5分钟搞定消息永久保存