Postgresql:如何根据百分比对项目进行分组

时间:2017-12-04 08:58:02

标签: sql postgresql

    store_id   product_name   quantity
       1          apple          10
       1          orange         12
       1          grapes          9
       1          mango          17
       2          chicken        112
       2          beef           90
       2          pork           89
       2          lamb           115

我想根据按照store_id分组的Grandtotal的百分比将其从最高和最低50%分组,并将底部产品标记为'其他' 看起来像这样的东西:

     store_id    product_name    percent
        1           mango         35.42%
        1           orange        25.00%
        1           OTHER         20.83%
        1           OTHER         18.75%
        2           lamb          28.33%
        2           chicken       27.59%
        2           OTHER         22.17%
        2           OTHER         21.92%

这可能吗?我真的很难谷歌这就是我来这里的原因。谢谢!

3 个答案:

答案 0 :(得分:1)

假设tablename为gt,则:

t=# with a as (select *,round( quantity * 100.0 / sum(quantity) over(partition by store_id), 2) r from gt)
,b as (select *, sum(r) over (partition by store_id order by r desc) from a)
select store_id, case when coalesce(lag(sum) over (partition by store_id) < 50 ,true) then product_name else 'OTHER' end product_name, r||'%' percent from b;
 store_id | product_name | percent
----------+--------------+---------
        1 | mango        | 35.42%
        1 | orange       | 25.00%
        1 | OTHER        | 20.83%
        1 | OTHER        | 18.75%
        2 | lamb         | 28.33%
        2 | chicken      | 27.59%
        2 | OTHER        | 22.17%
        2 | OTHER        | 21.92%
(8 rows)

答案 1 :(得分:0)

假设以下代码创建数据:

create table product(
  store int, 
  name text,
  qtd int
  );


insert into product values(1,' apple',10);
insert into product values(1,' orange',12);
insert into product values(1,' grapes',9);
insert into product values(1,' mango',17);
insert into product values(2,' chicken',112);
insert into product values(2,' beef',90 );
insert into product values(2,' pork',89 );
insert into product values(2,' lamb',115);

您可以使用此查询获得所需的输出:

with total_query as (
  SELECT store, sum(qtd) AS totalamount 
    FROM product 
    GROUP BY store 
  ),
count_query as (
  SELECT store, count(qtd) AS totalcnt 
    FROM product 
    GROUP BY store 

  ),
percent_query as (

select p.store, p.name, 
  round(p.qtd::float/(select totalamount from total_query
          where total_query.store = p.store)*100) as percent

  from product p

)

select store, 
case when row_number() over (
  partition by store order by percent desc)/
(select totalcnt from count_query where store = p.store)::float <= 0.5 
then 'Other' else name end, percent 

from percent_query p order by store, percent

| store |    name | percent |
|-------|---------|---------|
|     1 |  grapes |      19 |
|     1 |   apple |      21 |
|     1 |   Other |      25 |
|     1 |   Other |      35 |
|     2 |    beef |      22 |
|     2 |    pork |      22 |
|     2 |   Other |      28 |
|     2 |   Other |      28 |

答案 2 :(得分:0)

我会把它写成:

.state({
        name: '**login**',
        url: '/',
        templateUrl: your template,
        controller: 'controller name',
        controllerAs: 'vm',
        params: {
            **redirect**: null,
        },
    });

请注意,这会为每个select t.*, quantity / sum(quantity) over (partition by store_id) as ratio, (case when sum(quantity) over (partition by store_id order by quantity desc) - quantity < 0.5 * sum(quantity over (partition by store_id) as running_ratio then product_name else 'Other' end) as product_name from t; 生成一个单独的行,如您的示例所示。在实践中,我想要将它们结合起来。如果你想要(并且无法弄清楚如何去做),那就问另一个问题。