按百分位数将类似 sql 的查询的结果分组:在 Redshift / postgresql

Posted

技术标签:

【中文标题】按百分位数将类似 sql 的查询的结果分组:在 Redshift / postgresql【英文标题】:Breaking the results of an sql like query into groups by percentiles : In Redshift / postgresql 【发布时间】:2014-11-27 15:35:15 【问题描述】:

我有一组 group_name 及其计数。假设这来自以下陈述 - :

--sample input set --
select group_name, count(*) as group_count 
     from mytable group by group_name 
     order by group_count desc ;

    group_name  group_count 
    A 205
    B 200
    C 67
    D 55
    E 50 
    F 12
    and so on..

我想要将 groups_counts 的结果及其组名组织成 3 个组,例如 Head、core 和 tail - 每个组被理解为占 group_count 总数的 33%。所以 10、5 等将被它们各自的百分位数代替。而所有这些我都需要在 redshift(postgres 8.0.2) 中完成

作为第一级,应该是这样的,

-- 这不是一个有效的语法--

select case when group_count  >10 then group_name end ) as Head_group,
case when group_count  >5  and group_count <10 then query end ) as core_group, 
case when group_count  <5   then group_name end ) as tail_group, 
 from 
 ( select group_name, count(*) as group_count 
 from mytable group by group_name 
 order by group_count desc ) ;

在所需的语法中,选择将基于 sum(group_count) - 这将是所有组计数的总和。我如何在 postgressql 中得到相同的结果,更具体地说是在 Redshift 中。 请注意,Redshift 不支持创建函数。在 Redshift 中,prepare & set 也是可用的,但不是 prepare 语句。

   --sample output set---
    Head_group core_group tail_group 
    A           D          F
    B           E
    C
    --Alternative sample output set---
    Head_group 
    A
    B
    C
    core_group 
    D
    E
    tail_group 
    F

请注意,每个组可以返回不同数量的行。 在 mysql 中,我可以执行以下操作:

set @total_group_count =(select count(*) from mytable ) ;
set @percentile_group_count = ( select @total_group_count*(30/100))  ; 

参考我的相关问题: Storing the results of a prepared statement as a table in mysql?

【问题讨论】:

您能否提供一个样本输入集和样本期望输出集的完整示例?例如,您给出的输出集显然不是典型 SELECT 语句的结果。输出是否可以是每个输入行一行,但带有一个关于它将被分配到哪个组(头、核心、尾)的标识符? @JohnR 输出是否可以是每个输入行的一行,但带有一个标识符,说明它将被分配到哪个组(头部、核心、尾部)? -> 是的。我的意思是,我需要根据百分位数(按计数排序)在逻辑上将组分成 3 组 - 由于 1 条语句给出 head、core 和 tail 或 3 条语句给出 head,实际结果可能是 3 行, core & tail - 每次调用一个。我只需要 group_name(s) 的实际名称作为三个逻辑组中每一个的结果,如上所述。 为第一个结果和更多视觉效果添加了选择语句 【参考方案1】:

ntile 窗口函数是您最想在这里使用的。

它可以用于您的查询:

select group_name, count(*) as group_count,
       ntile(3) over(order by group_count desc) AS group_ntile
     from mytable group by group_name 
     order by group_count desc;

这应该将group_count 列的(降序)值分成三个相等的组。然后,您可以在 CASE 语句中使用 group_ntile 值来根据它所在的组执行您想要的操作。

根据Redshift 文档,ntile 似乎是可用的。

根据 OP 的评论进行编辑:

ntile 的参数是排名组的数量。

ntile 将结果(使用指定的 窗口函数 参数)存储到函数参数中指定的组数中。所以,如果你想要真正的percentiles,那么你应该使用ntile(100)

【讨论】:

考虑到我们使用 ntile(3),ntile 是否会确保分解是按百分位计算的? 知道了,谢谢。你是否也想尝试一下 - ***.com/questions/27122670/… - 我已经解决了这个问题,但它似乎仍然错过了一些东西。您对 3 组的原始答案是正确的,我正在验证分手是按 group_names 的总数,然后按组数排序 - 这隐含百分位数! 如果您正在查看该内容,请参阅编辑 4,这是我目前所了解的内容。

以上是关于按百分位数将类似 sql 的查询的结果分组:在 Redshift / postgresql的主要内容,如果未能解决你的问题,请参考以下文章

SQL中的Group By的查询过程多列分组的查询过程是怎样的?

来自有条件和无条件列的 SQL 查询分组的比率或百分比

Power Query M - 使用自定义聚合(百分位)按列值分组

根据给定的因子在 R 中按函数分组获取多列的百分比值

将总和转换为百分比

最少按不同分组 - SQL