导读
计算中位数可能是小学的内容,然而在数据库查询中实现却并不是一件容易的事。我们今天就来看看都有哪些方法可以实现。
注:本文所用MySQL版本无限制,所列题目均来源于LeetCode。
LeetCode数据库题目中关于中位数的主要有两道题,难度都是hard级别。两道题目无论是出现频率还是相关企业标签数,都属于比较靠前的位置,包括题解和讨论数量也是如此,足以见其热门程度。
569# 员工薪水中位数
题目描述:
预期答案:
解法1
既然是求解中位数,我们首先想到的是根据中位数的定义进行求解:奇数个数字时,中位数是中间的数字;偶数个数字时,中位数中间两个数的均值。本题不进行求解均值,而是将两个中位数全部显示。
根据定义,为了查询中位数,我们需要知道3点信息:
总数是奇数个还是偶数个
待查找数字总数
每个数字的排序编号
前两点信息在MySQL中非常简单,只需简单的count计数即可,而排序编号则需要借助辅助方法。在MySQL8.0以上版本引入了窗口函数后非常容易实现,但以前的版本则仅可通过自定义变量的方式获得排序值。这里如何对员工薪水进行分组排序不再展开,具体可参考历史文章一文解决所有MySQL分类排名问题。
在有了排名和数字总数之后,如何判断是中位数呢?这里计数字总数为N,则
N为奇数,中位数排序编号是(N+1)/2=N/2+0.5
N为偶数,中位数排序编号是N/2和N/2+1
进一步地,N为奇数和N为偶数是互斥的,求解出的中位数排序编号也是互斥的,也就是说3个排序编号不会同时取得整数,从而可以不加区分的直接判断即可。查询SQL语句:
1SELECT 2 e1.Id, e1.Company, e1.Salary 3FROM 4 (SELECT Id, Company, Salary, @rnk:=if(@pre=Company, @rnk+1, 1) rnk, @pre:=Company 5 FROM Employee, (SELECT @rnk:=0, @pre