数据库面试中的大坑!Group by 与 max联合使用
相信大家都做过返回各部门中薪水最高的员工信息,是否注意到里面的细节呢?
由于group by聚合函数的特殊性,会造成联合其他函数时产生各种各样的错误,尤其max和group by使用最为频繁,今天通过mysql案例揭示其背后的错误原因,并提出解决方法。首先我们先来了解下group by函数。
1、group by函数的说明:
如表1
执行如下SQL语句:
`SELECT` `name` `FROM` `test` `GROUP` `BY` `name`
如虚拟表3中的数据说明,group by聚合多行同一name下的多个id和number并压缩在了一行。
详见https://blog.csdn.net/yulutian/article/details/93247203
2、问题关键
由于mysql的表中一行只能对应一行数据,所以才会造成和max函数混合使用的错误。当使用max函数之后,一个group中的多行数据,只会显示第一行数据,
案例2:
原表salaries的信息
我们现在选择每个部门下最大工资对应的员工
select max(s.salary) , s.emp_no, s.dp from salaries s group by s.dp order by s.emp_no
查询的结果!!
注意到部门(dp)7中,最高工资为员工编号为10012、10010、10011对应的工资为700,怎么会出现10001员工了呢?
如果你还记得group by函数的话,就不难解释了,以dp分组的虚拟表中的7组员工中一共有4行,第一行就是员工10001,所以该员工就被显示出来了。
3、解决问题
知道了问题所在,如何解决问题呢?
我们可以了解到在使用max(salary)和group by(dp)函数时,只有返回列(salary,dp)是正确对应的,其他的列均不正确,所以可以将这两列作为子查询结果
select ss.emp_no , ss.salary , ss.dp
from
(select max(s.salary) as ms, s.dp from salaries s
group by s.dp order by s.emp_no) as temp
join salaries ss
where ss.salary = temp.ms and ss.dp =temp.dp
order by ss.emp_no;
结果: 可以正确的返回每组中最大工资的员工编号!