MySQL:计算派生值的中位数

Posted

技术标签:

【中文标题】MySQL:计算派生值的中位数【英文标题】:MySQL: calculate median of a derived value 【发布时间】:2016-09-02 03:54:53 【问题描述】:

根据标题,我正在尝试计算派生字段的中值:

SELECT
    TIMESTAMPDIFF(DAY, T1.time1, T2.time2) as diff
FROM table1 T1 JOIN table2 T2 ON ...
WHERE ...
GROUP BY ...

计算平均值很简单

SELECT
    AVG(F.diff) as average 
FROM (
    //subquery above
) F;

但是四处搜索我还没有找到计算中位数的方法,因为大多数解决方案似乎都涉及将列的表连接到自身。我这样做的唯一方法是输入两次子查询。这个子查询不是一个很快的,所以除非有人能确认 mysql 会优化冗余并且只执行一次子查询,否则我真的很想避免这种解决方案。

【问题讨论】:

【参考方案1】:

使用group_concat() 有一个技巧,但这可能不起作用(因为中间字符串长度)。更好的方法是简单地枚举行,然后使用条件聚合。不过,这需要两个级别的枚举:

SELECT TIMESTAMPDIFF(DAY, T1.time1, T2.time2) as diff,
       AVG(CASE WHEN 2*@rn IN (cnt - 1, cnt, cnt + 1 THEN value END) as median
FROM (SELECT *,
             (@max := if(@g = concat_ws(':', <group by columns>>), @max,
                         if(concat_ws(':', <group by columns>>), rn, rn)
                        )
             ) as cnt 
      FROM (SELECT . . .,
                   (@rn := if(@g = concat_ws(':', <group by columns>>), @rn + 1,
                              @g := concat_ws(':', <group by columns>>), 1, 1)
                             )
                   ) as rn
            FROM table1 T1 JOIN table2 T2 ON ... CROSS JOIN
                 (SELECT @g := '', @rn := 0) params
            WHERE ...
            ORDER BY <group by columns>, <ordering column>
           ) t CROSS JOIN
           (SELECT @g1 := '', @max := -1) params
      ORDER BY <group by columns>, <ordering column desc>
     ) t
GROUP BY ...

【讨论】:

以上是关于MySQL:计算派生值的中位数的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL 中分析并形成分位数并计算落在各个分位数中的值的百分比

计算向量中存储的值的中位数 - C++?

计算百分位数以去除异常值的快速算法

用 Mysql 计算中位数

计算组内移动中位数

MySQL中位数计算方法