一 引言
上一篇 Mysql 排序查询第N项 / 前N项(三种方法)已经总结了取前N项和倒数前N项的问题,这一篇主要解决分组后查询前N项/第N项问题
例如:查询每个员工最高薪资/每个员工第二薪资/每个员工最低薪资/各个品类销量前十的商品
二 Group By 的作用
说到分组,一般离不开group by语句。所以我们先看看group by到底有什么作用
1. group by直接使用,不搭配聚合函数(sum,average,count等),结果是取出每个分类字段的第一条记录(这里的分类字段是emp_no)
2. 搭配聚合函数(sum,average,count等),结果是根据分类字段进行加总、平均、计数
三 每个员工的最高工资和最低工资
四 每个员工的第二高工资
1. 为什么不能用 group by+ order by +limit
因为 limit 1,1 只能取出整个表的第二行,不能分组取各个组的第二行
2. 排名法
其实就是Mysql 排序查询第N项 / 前N项(三种方法)里面的排名法。原理:假如 a 排第10,意味着前面有9个数比a大,有10个数大于等于a, 求某个数的排名就是求前面有几个数大于等于这个数
思路:重复用salaries表,命名为s1,s2。用where语句s1.salary<=s2.salary筛选出所有大于等于s1.salary的s2.salary。然后统计每个s1.salary有多少个s2.salary大于等于它,就能得到每个s1.salary的排名
那么分组取第N项的排名法和上文有什么不一样呢。区别在于:排序查询前N项时,s1.salary<=s2.salary筛选出的是全表所有薪资中大于等于s1.salary的s2.salary。而我们要的是员工和自己的其他工资对比,是在员工自己的历史工资里面筛选,而不是在全表所有员工薪资里面筛选。转化为mysql语言就是,要在以员工编号为依据的分组里面筛选。因此,这里的排名法多了一个条件 s1.emp_no = s2.emp_no。
2.1 第一步
重复使用salaries表,分别命名为s1,s2。用 where s1.emp_no = s2.emp_no 将两个相同的表连接
保证只有员工编号相同的s1.salary 和s2.salary才能匹配上。
2.2 第二步
增加where条件:s1.salary<=s2.salary。 筛选出所有小于等于s1.salary 的 s2.salary
2.3 第三步
统计每个s1.salary有几个小于等于它的s2.salary,也就是s1.salary的排名
2.4 完整代码
不用group by 。
五 每个员工的倒数第二工资
方法和上面一样,只是把s1.salary<=s2.salary 换成s1.salary >= s2.salary
不用group by
六 每个员工最低工资减去第二低工资
思路:查出每个员工的最低工资,作为临时表a,查出每个员工的第二低工资作为临时表b。将a,b作为from 的子查询,用where 语句关联两个表