【问题标题】:PERCENTILE_CONT() returns same value regardless of input parameter无论输入参数如何,PERCENTILE_CONT() 都返回相同的值
【发布时间】:2018-04-12 20:57:00
【问题描述】:

我想获取表格的第 5、50、95 个百分位数

SELECT col1, col2, col3, AVG(col4), STD(col4), 
    PERCENTILE_CONT(0.05) WITHIN GROUP (ORDER BY col4) 
        OVER (PARTITION BY col1, col2, col3) as 5th_percentile, 
    PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY col4)  
        OVER (PARTITION BY col1, col2, col3) as 50th_percentile, 
    PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY col4)  
        OVER (PARTITION BY col1, col2, col3) as 95th_percentile
FROM table
GROUP BY col1, col2, col3
LIMIT 100

我最终得到的是 5th_percentile == 50th_percentile == 95th_percentile

AVG(col4)   STD(col4)   5th_percentile   50th_percentile  95th_percentile
300.000000  0.000000    300.000000       300.000000       300.000000
67.076600   16.968851   82.031792        82.031792        82.031792
66.166136   11.452172   78.348846        78.348846        78.348846
544.262809  68.269014   605.797302       605.797302       605.797302
22.523138   1.820358    24.000000        24.000000        24.000000

怎么了?

编辑:数据库是 MemSQL

【问题讨论】:

  • 哪个dbms?????? SQL 只是很多厂商使用的一种语言!!
  • 它使用 memsql,我相信它的语法与 MySQL 相似
  • 然后将标签添加到您的问题中。你不想要任何东西给你一个解决方案,但你不能使用它,因为它用于错误的 dbms。
  • 刚刚做到了!不过,我还没有在 stackoverflow 上看到太多 memsql 解决方案,所以我不想阻止任何不熟悉的人回答他们将在他们的 dbms 上做什么

标签: sql singlestore


【解决方案1】:
WITH a AS (
SELECT col1, col2, col3, 
        PERCENTILE_CONT(0.05) WITHIN GROUP (ORDER BY col4) 
            OVER (PARTITION BY col1, col2, col3) as 5th_percentile,
        PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY col4) 
            OVER (PARTITION BY col1, col2, col3) as 50th_percentile,
        PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY col4) 
            OVER (PARTITION BY col1, col2, col3) as 95th_percentile
FROM table
)
SELECT DISTINCT col1, col2, col3, 5th_percentile, 50th_percentile, 95th_percentile
FROM a
LIMIT 100

这行得通,看起来你不能用 percentile_cont 进行分组

【讨论】:

    【解决方案2】:

    窗口函数 GROUP BY 子句之后运行。 GROUP BY 每组生成一行,这就是 PERCENTILE_CONT 窗口函数都返回相同值的原因。

    您想先计算窗口函数,然后再计算 GROUP BY。您可以通过将窗口函数放在内部子选择中,将 GROUP BY 放在外部选择中来做到这一点。

    这里是来自 postgres 的文档,它解释了窗口函数与 group by 的关系(这是标准的 ANSI SQL,MemSQL 做同样的事情):

    https://www.postgresql.org/docs/current/static/tutorial-window.html

    窗口函数考虑的行是查询的 FROM 子句生成的“虚拟表”中​​的行,这些行由其 WHERE、GROUP BY 和 HAVING 子句(如果有)过滤。例如,由于不满足 WHERE 条件而被删除的行不会被任何窗口函数看到。一个查询可以包含多个窗口函数,这些函数通过不同的 OVER 子句以不同的方式对数据进行切片,但它们都作用于由该虚拟表定义的同一行集合。

    请注意,在 MemSQL 中,如果您在查询中使用未分组或聚合的列,例如 col4,您会从组中的行中获取任意值,即它的行为类似于 ANY_VALUE 聚合。在 MemSQL 的未来版本中,此查询将改为返回错误,以帮助您避免编写具有此类意外行为的查询。

    【讨论】:

      【解决方案3】:

      PERCENTILE_CONT()——至少在某些数据库中——可以是聚合函数或窗口函数。

      我认为正在发生的事情是在聚合之后 计算该值——我不知道为什么。老实说,我希望代码会出现语法错误,因为 col4 没有聚合。换句话说,(ORDER BY MAX(col4)) 应该有效,但 (ORDER BY col4) 无效,因为百分位数是在聚合之后计算的。

      但请尝试不使用OVER 子句:

      SELECT col1, col2, col3, AVG(col4), STD(col4), 
             PERCENTILE_CONT(0.05) WITHIN GROUP (ORDER BY col4)  as 5th_percentile, 
             PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY col4) as 50th_percentile, 
             PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY col4) as 95th_percentile
      FROM table
      GROUP BY col1, col2, col3
      LIMIT 100;
      

      编辑:

      您的数据库似乎不支持 PERCENTILE_CONT() 作为聚合函数。没有考虑味道。大多数都这样做。

      解决方法是SELECT DISTINCT:

      SELECT DISTINCT col1, col2, col3,
             AVG(col4) OVER (PARTITION BY col1, col2, col3),
             STD(col4) OVER (PARTITION BY col1, col2, col3),
             PERCENTILE_CONT(0.05) WITHIN GROUP (ORDER BY col4) OVER (PARTITION BY col1, col2, col3)  as 5th_percentile, 
             PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY col4) OVER (PARTITION BY col1, col2, col3) as 50th_percentile, 
             PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY col4) OVER (PARTITION BY col1, col2, col3) as 95th_percentile
      FROM table
      LIMIT 100;
      

      或者使用子查询。

      【讨论】:

      • 我不能带走 OVER() 语句,但是当我带走 OVER() 语句的参数时,它会应用百分位排名而不分组。虽然,它确实为第 5、第 50 和第 95 个百分位数返回了不同的值,我认为这是朝着正确方向迈出的一步。编辑:为清楚起见,当我删除 OVER() 语句的参数时,col1、col2、col3 的不同值都具有完全相同的第 5、第 50 和第 95 个百分位值,而在每组 col1、col2、col3 之前会有不同的值 - 这是期望的结果
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-07
      • 1970-01-01
      • 2018-11-08
      • 1970-01-01
      相关资源
      最近更新 更多