【问题标题】:Calculate cumulative percentiles using SQL for a group/partition使用 SQL 计算组/分区的累积百分位数
【发布时间】:2021-09-23 01:10:30
【问题描述】:

我想计算 SQL 中给定分区/组的 累积 百分位数。例如输入数据看起来像 -

CustID     Product ID     quantity_purchased    
1          111                2
2          111                3
3          111                2 
4          111                5
1          222                2
2          222                6
4          222                7
6          222                2

我想获得每个产品 ID 组的累积百分位数。输出应该是 -

Product ID    min      25%      50%      75%     max
    111        2        2       2.5      3.5      5
    222        2        2       2.5      5.25     7     

所以,基本上对于产品 ID 111,我只需要为产品 ID 111 取 quantity_purchased 的百分位数,但是当我在列中继续进行时,百分位数应该是产品 ID 222 的累积含义将考虑产品 ID 111 和产品 ID 222 (2,3,2,5,2,6,7,2) 的 quantity_purchased 值进行计算。同样,如果数据中有产品 ID 333,那么对于产品 ID 333,我将根据与产品 111、产品 222 和产品 333 关联的所有数量购买值计算百分位数,并将结果存储在产品 333 行中。如何使用 SQL 实现这一点?

【问题讨论】:

  • 2.5、5.25是什么意思?
  • @AIMINPAN 所以要计算产品 ID 222 的百分位数,我将考虑产品 ID 111 和产品 ID 222 (2,3,2,5,2,6,7,2) 的所有数量购买值并在所有这些上做一个百分位。我在问题中添加了更多细节

标签: sql snowflake-schema


【解决方案1】:

非常很好奇,但我认为您需要为每个产品 id 扩展数据:

select t.product_id, min(t2.quantity_purchased), max(t2.quantity_purchased),
       percentile_cont(0.25) within group (order by t2.quantity_purchased),
       percentile_cont(0.50) within group (order by t2.quantity_purchased),
       percentile_cont(0.75) within group (order by t2.quantity_purchased)
from t join
     t t2
     on t2.product_id <= t.product_id
group by t1.product_id;

【讨论】:

  • 不错的戈登!我开始走下阻碍进步的累积漏洞。很好的答案和令人敬畏的棘手问题。
【解决方案2】:

这使用了PERCENTILE_CONT 而不是PERCENTILE_DISC,返回的关键差异 val 是基于使用线性插值的连续分布,其中值不完美排列 - 根据您的用例,这可能会提供更准确的数据点。 :-)

select
    ProductID,
    min(Quantity_Purchased::float) min,
    PERCENTILE_CONT(.25) WITHIN GROUP (ORDER BY Quantity_Purchased ) as "25%",
    PERCENTILE_CONT(.50) WITHIN GROUP (ORDER BY Quantity_Purchased ) as "50%",
    PERCENTILE_CONT(.75) WITHIN GROUP (ORDER BY Quantity_Purchased ) as "75%" ,
    max(Quantity_Purchased) max
from
    cte
group by
    1

复制|粘贴|在雪花中运行

with cte as (
select
    1 CustID,
    111 ProductID,
    2 Quantity_Purchased
union
select
    2 CustID,
    111 ProductID,
    3 Quantity_Purchased
union
select
    3 CustID,
    111 ProductID,
    2 Quantity_Purchased
union
select
    4 CustID,
    111 ProductID,
    5 Quantity_Purchased
union
select
    1 CustID,
    222 ProductID,
    2 Quantity_Purchased
union
select
    2 CustID,
    222 ProductID,
    6 Quantity_Purchased
union
select
    4 CustID,
    222 ProductID,
    7 Quantity_Purchased
union
select
    6 CustID,
    222 ProductID,
    2 Quantity_Purchased
)  
select
    ProductID,
    min(Quantity_Purchased::float) min,
    PERCENTILE_CONT(.25) WITHIN GROUP (ORDER BY Quantity_Purchased ) as "25%",
    PERCENTILE_CONT(.50) WITHIN GROUP (ORDER BY Quantity_Purchased ) as "50%",
    PERCENTILE_CONT(.75) WITHIN GROUP (ORDER BY Quantity_Purchased ) as "75%" ,
    max(Quantity_Purchased) max
from
    cte
group by
    1

【讨论】:

  • 这不是预期的输出。对于产品 ID 222,50% 平铺的预期输出为 2.5,75% 平铺的预期输出为 5.25。 (检查有问题的预期输出)因此,基本上对于产品 ID 111,我只需要为产品 ID 111 取 quantity_purchased 的百分位数,但是当我们转到产品 ID 222 时,百分位数将是累积的,这意味着将考虑计算百分位数quantity_purchased 产品 ID 111 和产品 ID 222 的值
猜你喜欢
  • 2021-09-22
  • 1970-01-01
  • 2017-03-03
  • 2021-06-19
  • 1970-01-01
  • 2021-10-15
  • 1970-01-01
  • 2022-01-22
  • 2012-10-28
相关资源
最近更新 更多