【问题标题】:Calculating a simple median on a column in MySQL在 MySQL 中计算列的简单中位数
【发布时间】:2020-11-09 16:44:17
【问题描述】:

我正在努力寻找简单中位数问题的解决方案。给定一个只有一列的表 my_table

my_column | 
----------|
10        |
20        |
30        |
40        |
50        |
60        |

如何调用函数返回 35 的中位数?

当我只想返回中间值时,我不知道如何使这个语法起作用:

SELECT
  PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY my_column) OVER ( PARTITION BY my_column)
FROM
  my_table

【问题讨论】:

  • 35 是平均值,而不是中位数。
  • @BillKarwin 一点也不真实。上述数据集没有单个中值,因为它有 偶数 个值。因此,统计学家通常会将 30 和 40 的 均值 报告为中位数。在这种情况下,它是 35,巧合的是,这也是平均值。
  • 点了,我收回我的评论。 :)
  • 对不起,我应该使用更好的样本数据来保持更清晰!
  • 撤回评论的一种方法是删除它。

标签: mysql sql mariadb common-table-expression median


【解决方案1】:

这是我在 MySQL 8.0 中测试的解决方案:

with ranked as (
  select my_column, 
    row_number() over (order by my_column) as r,
    count(my_column) over () as c 
  from my_table
),
median as (
  select my_column 
  from ranked 
  where r in (floor((c+1)/2), ceil((c+1)/2))
)
select avg(my_column) from median

输出:

+----------------+
| avg(my_column) |
+----------------+
|        35.0000 |
+----------------+

我从https://stackoverflow.com/a/7263925/20860借用了这个方法,但把它改成了 MySQL 8.0 CTE 和窗口函数。

【讨论】:

    【解决方案2】:

    我只会使用distinct,并带有一个空的OVER() 子句:

    SELECT DISTINCT PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY my_column) OVER () median
    FROM my_table
    

    【讨论】:

    • 注意:此答案不适用于 MySQL,仅适用于 MariaDB(PERCENTILE_CONT 在 MySQL 中不存在)。
    【解决方案3】:

    你可以试试:

    SELECT col_median
    FROM
    (
        SELECT PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY my_column) OVER () AS col_median
        FROM my_table
    ) t
    LIMIT 1;
    

    Demo

    注意:PERCENTILE_CONT 函数是一个窗口 函数,在这种情况下,它的输出只能在整个列被扫描后才能确定。结果,上面子查询的输出实际上是您的列,以及一个新列,在所有行中具有相同的中值。但是,由于您只想将中值报告为单个数字,因此我使用LIMIT 1 外部查询来获取该单个中值。

    【讨论】:

    • 完美!如果我也想获得 0.25、0.50、0.75、0.90 的百分位数,我会遵循同样的模式吗?
    • 对于整个表,是的,这应该可以工作(玩弄我的演示链接来尝试一下)。
    • 根据该演示链接,这适用于 MariaDB,但不适用于 MySQL8.0 或更早版本。
    猜你喜欢
    • 2010-11-20
    • 2022-12-11
    • 2014-11-08
    • 2018-01-24
    • 2011-07-21
    相关资源
    最近更新 更多