MySQL中位數計算方法


在網上搜到的一種算法是利用自增長變量進行排序,然后再根據位置序號取。感覺有些復雜了。

一.   group_concat來的省事些, 缺點是 group_concat默認有總長度限制,不能對太多的數求中位數。可以修改長度限制,也可以用第二種方法

1. 按順序聚合,逗號分隔,並計數

group_concat( number order by number asc) 

2. 根據逗號拆分,判斷奇偶數去截取中間位置的那個數

 

具體代碼如下:

SELECT 
            doctor_name doctor,  -- 分組
	    count(1) patientNum,  -- 總數
	    group_concat(dnt order by dnt asc),
	    substring_index(SUBSTRING_INDEX(group_concat(dnt order by dnt asc),',',(count(1)+1) div 2),',',-1)  dnt,
	    case when count(1)%2=1 then substring_index(SUBSTRING_INDEX(group_concat(dnt order by dnt asc),',',(count(1)+1) div 2),',',-1) 
else (substring_index(SUBSTRING_INDEX(group_concat(dnt order by dnt asc),',',(count(1)+2) div 2),',',-1) + substring_index(SUBSTRING_INDEX(group_concat(dnt order by dnt asc),',',count(1) div 2),',',-1))/2 end mid_dnt FROM ( SELECT distinct doctor_name, record_id, dnt from rp_green_channel_patient_detaile where dnt is not null AND visit_day >= '2020-03-30' AND visit_day <= '2020-06-27' ) AS a group by doctor_name

 二.   組內排序

比如: 計算每個病種的住院費用中位數,數據如下

思路:

(1) 對每個病種下的,住院費用按照從小到大生成序號,生成a表
(2) 對每個病種的總人數進行計數, 生成b表
(3) a表和b表進行關聯,取a表最中間的1個數或兩個數:
     如果總數是奇數,那么 ceil(b表總人數/2) 或 floor(b表總人數/2 +1) 即為中間那個數的序號
     如果總數是偶數,那么中間兩個數依次是 ceil(b表總人數/2)、floor(b表總人數/2 +1)
     所以兩表關聯后,取ceil(b表總人數/2) 或 floor(b表總人數/2 +1) 兩個位置的數,再取平均值即為中位數


代碼:

    select
      a.base_group_name,
      round(avg(total_fee),1) median_fee                              -- 對已取出的兩個數求平均值
    from 
    ( 
           select 
                  x.*,
                  if(@p2=base_group_name,@r2:=@r2+1,@r2:=1) as rank,   -- 在每個病種內進行排序,生成序號
                  @p2:=base_group_name
           from 
           (
           select
                     base_group_name,
                    record_id,
                      total_fee
           from ads_gc_patient_detail
           )x
           inner join 
           (
                     SELECT @p2:=NULL,@r2:=0                         -- 排序方式的初始化參數
           ) y
           order by base_group_name,total_fee asc                    -- 組內根據住院總費用增序排列
    )a
    join 
    (  
           select
                  base_group_name,
                  count(1) cnt
           from ads_gc_patient_detail
             group by base_group_name
    )b 
    on a.base_group_name=b.base_group_name 
         and (floor(b.cnt/2+1)=a.rank or ceil(b.cnt/2)=a.rank)    -- 取中間的兩個數(組總數為偶數)或一個數(組總數為奇數)
    group by a.base_group_name

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM