員工薪水中位數
題目描述:
預期答案:
解法1
既然是求解中位數,我們首先想到的是根據中位數的定義進行求解:奇數個數字時,中位數是中間的數字;偶數個數字時,中位數中間兩個數的均值。本題不進行求解均值,而是將兩個中位數全部顯示。
根據定義,為了查詢中位數,我們需要知道3點信息:
-
總數是奇數個還是偶數個
-
待查找數字總數
-
每個數字的排序編號
前兩點信息在MySQL中非常簡單,只需簡單的count計數即可,而排序編號則需要借助輔助方法。在MySQL8.0以上版本引入了窗口函數后非常容易實現,但以前的版本則僅可通過自定義變量的方式獲得排序值。這里如何對員工薪水進行分組排序不再展開
在有了排名和數字總數之后,如何判斷是中位數呢?這里計數字總數為N,則
-
N為奇數,中位數排序編號是(N+1)/2=N/2+0.5
-
N為偶數,中位數排序編號是N/2和N/2+1
進一步地,N為奇數和N為偶數是互斥的,求解出的中位數排序編號也是互斥的,也就是說3個排序編號不會同時取得整數,從而可以不加區分的直接判斷即可。
查詢SQL語句:
SELECT e1.Id, e1.Company, e1.Salary FROM (SELECT Id, Company, Salary, @rnk:=if(@pre=Company, @rnk+1, 1) rnk, @pre:=Company FROM Employee, (SELECT @rnk:=0, @pre:=null)init ORDER by Company, Salary, Id)e1 JOIN (SELECT Company, count(*) cnt FROM Employee GROUP by Company) e2 using(Company) WHERE e1.rnk in (cnt/2+0.5, cnt/2, cnt/2+1)
查詢效率:
解法2
除了根據中位數的排序編號來定位其位置,實際上還可以換種思路但仍然是在其排序編號上做文章:如果一個數是中位數,那么就意味着正序和逆序時其位置是一致的:更嚴謹的說,奇數個數字是正逆序排序一致,偶數個數字時,兩中位數順序要互換一下,也就是相差為1。進而,我們發現無論數字總數是奇數還是偶數,中位數的正逆排序相差要么為0,要么為1。根據這一性質,我們分別實現正逆兩遍排序,然后判斷數字的排序編號即可。
查詢SQL語句:
SELECT e1.Id, e1.Company, e1.Salary FROM (SELECT Id, Company, Salary, @rnk:=if(@pre=Company, @rnk+1, 1) rnk, @pre:=Company FROM Employee, (SELECT @rnk:=0, @pre:=null)init ORDER by Company, Salary, Id)e1 JOIN (SELECT Id, Company, Salary, @rnk:=if(@pre=Company, @rnk+1, 1) rnk, @pre:=Company FROM Employee, (SELECT @rnk:=0, @pre:=null)init ORDER by Company, Salary DESC, Id DESC)e2 on e1.Id=e2.Id WHERE abs(e1.rnk - e2.rnk)<=1
查詢效率:
解法3
前2種解法都是根據中位數的定義在數字排序編號上作文章,下面是一個對中位數性質更深的理解(摘抄自官方題解)
根據定義,我們來找一下 [1, 3, 2] 的中位數。首先 1 不是中位數,因為這個數組有三個元素,卻有兩個元素 (3,2) 大於 1。3 也不是中位數,因為有兩個元素小於 3。對於 2 來說,大於 2 和 小於 2 的元素數量是相等的,因此 2 是當前數組的中位數。當數組長度為 偶數,且元素唯一時,中位數等於排序后 中間兩個數 的平均值。對這兩個數來說,大於當前數的數值個數跟小於當前數的數值個數絕對值之差為 1,恰好等於這個數出現的頻率。
結論:不管數組長度是奇是偶,也不管元素是否唯一,中位數出現的頻率一定大於等於 大於它的數 和 小於它的數 的絕對值之差。
好吧,力扣的官方題解讀起來總是這么生澀。不過細品之下,我們還是可以發現這個結論是對的。【好像說了句廢話】
根據中位數的這一性質,可以寫出如下查詢語句:
SELECT e1.Id, e1.Company, e1.Salary FROM Employee e1, Employee e2 WHERE e1.Company = e2.Company GROUP BY e1.Company , e1.Salary HAVING SUM(e1.Salary = e2.Salary) >= ABS(SUM(SIGN(e1.Salary - e2.Salary))) ORDER BY e1.Id
查詢效率:
實際上,雖然3種解法均為兩表關聯,但由於解法3中涉及到相對更為復雜的計算,其效率竟然要比解法1和解法2中低太多。
所以,不妨想想奧卡姆剃刀原理,大道至簡、大巧不工、簡單之美!