【问题标题】:How to calculate median in AWS Redshift?如何计算 AWS Redshift 中的中位数?
【发布时间】:2014-01-24 14:47:36
【问题描述】:

大多数数据库都有一个用于计算中位数的内置函数,但我在 Amazon Redshift 中看不到任何中位数。

您可以使用 nth_value() 和 count() 分析函数的组合来计算中位数,但这似乎很麻烦。如果分析数据库没有用于计算中位数的内置方法,我会感到非常惊讶,所以我假设我错过了一些东西。

http://docs.aws.amazon.com/redshift/latest/dg/r_Examples_of_NTH_WF.html http://docs.aws.amazon.com/redshift/latest/dg/c_Window_functions.html

【问题讨论】:

    标签: amazon-redshift


    【解决方案1】:

    试试NTILE 功能。

    您可以将数据分成 2 个排序组,然后从第一组中选择最小值。这是因为在具有奇数个值的数据集中,第一个 ntile 将比第二个多 1 个值。这种近似应该适用于大型数据集。

    create table temp (num smallint);
    insert into temp values (1),(5),(10),(2),(4);
    
    select num, ntile(2) over(order by num desc) from temp ;
     num | ntile 
    -----+-------
      10 |     1
       5 |     1
       4 |     1
       2 |     2
       1 |     2
    
    select min(num) as median from (select num, ntile(2) over(order by num desc) from temp) where ntile = 1;
     median 
    --------
          4
    

    【讨论】:

    • 将此标记为已接受的答案,因为它似乎在理论上应该有效,但我还没有实际测试过。好主意!
    【解决方案2】:

    如果我正在寻找足够接近的答案,我通常使用NTILE 函数将数据分成两组。但是,如果我想要准确的中位数(例如,一组偶数行的中点),我会使用AWS Redshift Discussion Forum 上建议的技术。

    这种技术按升序和降序对行进行排序,然后如果有奇数行,则返回中间行的平均值(即row_num_asc = row_num_desc),即中间行本身.

    CREATE TABLE temp (num SMALLINT);
    
    INSERT INTO temp VALUES (1),(5),(10),(2),(4);
    
    SELECT
      AVG(num) AS median
    FROM
    (SELECT
      num,
      SUM(1) OVER (ORDER BY num ASC) AS row_num_asc,
      SUM(1) OVER (ORDER BY num DESC) AS row_num_desc
    FROM
      temp) AS ordered
    WHERE
      row_num_asc IN (row_num_desc, row_num_desc - 1, row_num_desc + 1);
    
     median 
    --------
          4
    

    如果有偶数行,则返回中间两行的平均值。

    INSERT INTO temp VALUES (9);
    
    SELECT
      AVG(num) AS median
    FROM
    (SELECT
      num,
      SUM(1) OVER (ORDER BY num ASC) AS row_num_asc,
      SUM(1) OVER (ORDER BY num DESC) AS row_num_desc
    FROM
      temp) AS ordered
    WHERE
      row_num_asc IN (row_num_desc, row_num_desc - 1, row_num_desc + 1);
    
     median 
    --------
        4.5
    

    【讨论】:

      【解决方案3】:

      我也遇到了困难,但从亚马逊那里得到了一些帮助。从 2014-06-30 版本的 Redshift 开始,您可以使用 PERCENTILE_CONTPERCENTILE_DISC 窗口函数来执行此操作。

      它们使用起来有点奇怪,因为它们会将中位数(或您选择的任何百分位数)添加到 每个 行。你把它放在一个子查询中,然后取中间列的 MIN(或其他)。

      # select count(num), min(median) as median from (select num, percentile_cont (0.5) within group (order by num) over () as median from temp); count | median -------+-------- 5 | 4.0

      (复杂的原因是窗口函数也可以进行自己的 mini-group-by 和 ordering,以同时为您提供许多组的中位数,以及其他技巧。)

      在偶数个值的情况下,CONT(inuous) 将在两个中间值之间进行插值,其中 DISC(rete) 将选择其中一个。

      【讨论】:

        【解决方案4】:

        截至 2014 年 10 月 17 日,Redshift 支持MEDIAN 窗口功能:

        # select min(median) from (select median(num) over () from temp);
         min 
        -----
         4.0
        

        【讨论】:

        • 链接更好的答案
        • 从表中选择不同的中位数(字段)而不是()
        • 当 postgres 将 percentile_cont 作为 ordered-set aggregate 时,Redshift 将其实现为窗口函数,这很奇怪。它迫使您在其顶部执行 distinctmin 聚合。
        猜你喜欢
        • 2015-04-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-28
        • 2021-01-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多