在SQL查询场景中,我们常常需要先对数据进行分组聚合,再找到每个分组中数值最小的记录对应的完整行信息,这时候单独使用MIN函数只能得到极小值本身,无法获取整行数据,需要结合关联子查询来实现需求。

MIN函数的基础用法
MIN函数是SQL中常用的聚合函数,作用是返回指定列的最小值,通常和GROUP BY子句配合使用实现分组聚合统计。它的基本语法如下:
-- 查询每个部门的最低工资 SELECT dept_id, MIN(salary) AS min_salary FROM employee GROUP BY dept_id;
上面的查询只能得到每个部门的部门ID和对应的最低工资数值,无法获取拿到最低工资的员工姓名、入职时间等其他字段信息,这时候就需要关联子查询来补充完整记录。
关联子查询的核心逻辑
关联子查询是指子查询中引用了外层查询的字段,子查询的执行会依赖外层查询的每一行数据。我们可以利用这个特性,先在外层查询中拿到分组维度,再在子查询中计算该分组下的极小值,最后匹配得到完整记录。
实现获取聚合极小值记录的完整方案
假设我们有如下的员工表employee,结构如下:
| 字段名 | 类型 | 说明 |
|---|---|---|
| emp_id | INT | 员工ID |
| emp_name | VARCHAR | 员工姓名 |
| dept_id | INT | 部门ID |
| salary | DECIMAL | 员工工资 |
| hire_date | DATE | 入职日期 |
现在需要查询每个部门中工资最低的员工的所有信息,实现SQL如下:
SELECT e1.emp_id, e1.emp_name, e1.dept_id, e1.salary, e1.hire_date
FROM employee e1
WHERE e1.salary = (
-- 关联子查询,计算当前部门的最低工资
SELECT MIN(e2.salary)
FROM employee e2
WHERE e2.dept_id = e1.dept_id
);
这个查询的执行逻辑是:外层查询遍历employee表的每一行数据,对于每一行对应的dept_id,子查询会计算该部门所有员工的最低工资,然后外层查询判断当前行的工资是否等于这个极小值,相等就保留该记录。
多条件极小值记录的查询
如果需求是获取每个部门中入职时间最早(也就是hire_date最小)的员工信息,只需要调整子查询中的聚合字段即可:
SELECT e1.emp_id, e1.emp_name, e1.dept_id, e1.salary, e1.hire_date
FROM employee e1
WHERE e1.hire_date = (
-- 计算当前部门的最早入职日期
SELECT MIN(e2.hire_date)
FROM employee e2
WHERE e2.dept_id = e1.dept_id
);
注意事项
- 如果同一个分组中存在多条记录的聚合字段值都等于极小值,上面的查询会返回所有符合条件的记录,这是符合预期的。
- 关联子查询的执行效率在大数据量场景下可能不如窗口函数,如果数据库支持窗口函数,也可以使用ROW_NUMBER()的方式实现,不过MIN函数加关联子查询的兼容性更好,适合所有关系型数据库。
- 子查询中的WHERE条件必须和外层查询的关联字段对应,否则会变成非关联子查询,无法正确匹配每个分组的极小值。
使用MIN函数结合关联子查询是获取聚合结果中极小值记录的通用方案,理解子查询和外层查询的关联逻辑是掌握这个方法的关键,实际使用时根据需求调整聚合字段和匹配条件即可。