Postgresql:如何从每个组/类别中选择前n%(%)条目

时间:2014-07-08 07:28:00

标签: sql database postgresql postgresql-9.1

我们是postgres的新手,我们有以下查询,我们可以从中选择每个类别的前N个记录。

 create table temp (
     gp char,
     val int
 );

 insert into temp values ('A',10);
 insert into temp values ('A',8);
 insert into temp values ('A',6);
 insert into temp values ('A',4);
 insert into temp values ('B',3);
 insert into temp values ('B',2);
 insert into temp values ('B',1);

 select a.gp,a.val
 from   temp a
 where  a.val in (
              select b.val
              from   temp b
              where  a.gp=b.gp
              order by b.val desc
             limit 2);

上述查询的输出就像这样

 gp   val
 ----------
 A    10
 A    8
 B    3
 B    2

但我们的要求不同,我们希望从n类未固定的每个类别中选择前n%记录,n基于每组中某些元素的百分比。

3 个答案:

答案 0 :(得分:13)

要根据每个组中行数的百分比检索行,您可以使用两个窗口函数:一个用于计算行,另一个用于为它们指定唯一编号。

select gp,
       val
from (
  select gp, 
         val,
         count(*) over (partition by gp) as cnt,
         row_number() over (partition by gp order by val desc) as rn
  from temp
) t
where rn / cnt <= 0.75;

SQLFiddle示例:http://sqlfiddle.com/#!15/94fdd/1


顺便说一句:使用char几乎总是一个坏主意,因为它是一个固定长度的数据类型,填充到定义的长度。我希望你只是为了设置这个例子而做的,不要在你的真实表格中使用它。

答案 1 :(得分:0)

参考a_horse_with_no_name的响应,您可以使用 percent_rank()

SELECT
    gp,
    val,
    pct_rank
FROM (
    SELECT
        gp,
        val,
        percent_rank() over (order by val desc) as pct_rank
    FROM variables.temp
    ) t
WHERE pct_rank <= 0.75;

然后,您可以设置最终的WHERE子句以返回所需的任何 percent_rank()阈值。

答案 2 :(得分:-1)

接受的答案对我不起作用。我找到了适合我的解决方案:

SELECT * FROM temp ORDER BY val DESC
     LIMIT (SELECT (count(*) / 10) AS selnum FROM temp )

这不是最佳的(性能),但可以正常工作