mysql子查询关键在于按场景选用where(条件过滤)、from(派生表)、select(标量补字段)三类位置:where中子查询须单值或列表,from中须带别名作临时表,select中须单行单列;jdbc执行需用preparedstatement防注入,并避免三层以上嵌套。

Java 中用 MySQL 子查询处理复杂嵌套逻辑,关键不是“写多层 SELECT 套 SELECT”,而是根据数据结构选对子查询类型,并配合 JDBC 安全执行。重点在于理解子查询的三种位置(WHERE、FROM、SELECT)各自适合什么场景,而不是强行嵌套。
WHERE 子句中用子查询做条件过滤
适用于“查满足某动态条件的数据”,比如找工资高于本部门平均值的员工。子查询先算出每个部门的平均工资,外层再比对。
- 子查询必须返回单值或列表,不能多列多行(除非用 IN 或 EXISTS)
- 避免在 WHERE 中写关联子查询不加别名或没索引,否则性能差
- 示例 SQL:
FROM employees e
WHERE e.salary > (
SELECT AVG(salary)
FROM employees e2
WHERE e2.department_id = e.department_id
);
FROM 子句中用子查询当临时表(派生表)
适合先聚合、再关联的场景,比如统计每个部门平均工资后,再和部门表连查部门名称。
- 子查询必须带别名(MySQL 强制要求)
- 外层可像普通表一样 JOIN、WHERE、ORDER BY
- 比多次查数据库或 Java 端拼数据更高效
- 示例 SQL:
FROM departments d
JOIN (
SELECT department_id, AVG(salary) AS avg_salary
FROM employees
GROUP BY department_id
) avg_sal ON d.id = avg_sal.department_id;
SELECT 列表中用标量子查询补字段
适合为每行补充一个独立计算值,比如查订单时顺带显示该客户历史订单总数。
- 子查询必须只返回 0 或 1 行 1 列(否则报错)
- 不支持 LIMIT,也不能返回多行
- 慎用于大数据量表,因每行都执行一次子查询
- 示例 SQL:
(
SELECT COUNT(*)
FROM orders o2
WHERE o2.customer_id = o.customer_id
) AS order_count_per_customer
FROM orders o;
JDBC 执行时要注意的细节
Java 端不是把 SQL 拼出来就完事,得兼顾安全与可维护性。
- 一律使用 PreparedStatement,防止 SQL 注入,尤其子查询里带用户输入时
- 子查询结果为空时,标量子查询返回 NULL,Java 取值要用 rs.getObject() 或判断 wasNull()
- 嵌套过深(比如三层以上)建议拆成多个查询 + Java 合并,避免 MySQL 优化器失效
- 对 JSON 字段做嵌套提取?别在 Java 里解析字符串,优先用 MySQL 8.0+ 的 JSON_TABLE 配合 JOIN(注意它不能放子查询 FROM 里)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











