在 aws athena 中计算百分位数

lmb*_*loo 3 sql case presto amazon-athena

我的查询结果正在 aws Quicksight 中使用。尽管quicksight提供了percentileCont()来为我们完成这项工作,但我想在查询中使用它而不是使用计算字段。

最终我想做的是创建一个点列,其中

under 25percentile -> 0
under 50 percentile -> 1 
under 75 percentile -> 2
rest -> 3
Run Code Online (Sandbox Code Playgroud)

取决于范围为 [a, b] 的列。

现在我找出每个百分位数的值并手动创建一个范围

With table as (
    SELECT *
         , cast(date_diff('day', last_transaction, current_date) as double) as col
)
SELECT *
     , case 
         when col between 0 and 25 then 0
         when col between 26 and 66 then 1
         when col between 67 and 193 then 2
         when col >= 194 then 3
       end as point
  FROM table;
Run Code Online (Sandbox Code Playgroud)

但是我想让它动态化,所以用 [min(col), 25percentile(col)] 代替 [0,25]。

以上查询输出

col   point
333     3
166     2
 96     1
 .
Run Code Online (Sandbox Code Playgroud)

添加了 NTILE() 感谢@Gordon Linoff

With table as (
    SELECT *
         , cast(date_diff('day', last_transaction, current_date) as double) as col
)
SELECT *
     , case 
         when col between 0 and 25 then 0
         when col between 26 and 66 then 1
         when col between 67 and 193 then 2
         when col >= 194 then 3
       end as point
      , NTILE(4) over(order by col) as pt
  FROM table;
Run Code Online (Sandbox Code Playgroud)

输出

col   point
0     1
0     1
0     1
 .
Run Code Online (Sandbox Code Playgroud)

似乎搞乱了 col 计算

Gor*_*off 6

您几乎描述了该ntile()功能:

SELECT t.*,,
       NTILE(4) OVER (ORDER BY col) - 1 as point
FROM table;
Run Code Online (Sandbox Code Playgroud)

两个注意事项:

  • NTILE(<n>)返回 1 到 n 之间的值
  • NTILE()确保生成的图块相等。这意味着边界上的值可能最终会出现在不同的容器中。

另一种将值放入单独的容器中(但容器可能具有不同大小)的替代方法是percent_rank()。在你的情况下:

SELECT t.*,,
       CEILING(PRECENT_RANK() OVER (ORDER BY col) * 4) - 1 as point
FROM table;
Run Code Online (Sandbox Code Playgroud)