按范围汇总值

时间:2014-02-27 19:33:31

标签: sql postgresql aggregate-functions generate-series

我有一个有利润和交易数量列的用户表:

enter image description here
...

我想平均三组用户的平均利润 - 交易数量相对较多,交易时平均数量,交易时数量较少。

要获得范围系列,我使用generate_series:

SELECT generate_series(
    max(transactions_year)/3,
    max(transactions_year),
    max(transactions_year)/3
)
FROM portfolios_static 

我确实得到了三个类别:

enter image description here

我需要一张像这样的桌子:

enter image description here

如何获得属于每个类别的用户的平均利润并计算属于每个类别的用户数?

2 个答案:

答案 0 :(得分:1)

这样做:

with s as
(SELECT max(transactions_year)/3 series FROM portfolios_static
 UNION ALL 
 SELECT max(transactions_year)/3 * 2 series FROM portfolios_static
 UNION ALL 
 SELECT max(transactions_year) series FROM portfolios_static
),
s1 as
(SELECT generate_series(
    max(transactions_year)/3,
    max(transactions_year),
    max(transactions_year)/3
) AS series
FROM portfolios_static
),
srn as
(SELECT series,
row_number() over (order by series) rn
from s),
prepost as
(select coalesce(pre.series,0) as pre,
 post.series as post
 from srn post
 left join srn pre on pre.rn = post.rn-1)
select pp.post number_of_deals_or_less,
avg(profit_perc_year) average_profit,
count(*) number_of_users 
from portfolios_static p INNER JOIN prepost pp 
ON p.transactions_year > pp.pre AND p.transactions_year <= pp.post
GROUP by pp.post
order by pp.post;
顺便说一下,我不得不抛弃generate_series并使用普通的UNION ALL,因为当max值不能被3整除时,generate系列不会返回正确的MAX()值。例如,如果你替换{{1} } CTE到

srn

您会注意到在某些情况下,系列中的最后一个值将小于srn as (SELECT series, row_number() over (order by series) rn from s1), -- use generate_series

SQL Fiddle

答案 1 :(得分:1)

这可以更简单,更快捷。假设没有条目有0个交易:

SELECT y.max_deals AS deals
     , avg(profit_perc_year) AS avg_profit
     , count(*) AS users
FROM  (
   SELECT (generate_series (0,2) * x.max_t)/3 AS min_deals
         ,(generate_series (1,3) * x.max_t)/3 AS max_deals
   FROM   (SELECT max(transactions_year) AS max_t FROM portfolios_static) x
   ) y
JOIN   portfolios_static p ON p.transactions_year >  min_deals
                          AND p.transactions_year <= max_deals
GROUP  BY 1
ORDER  BY 1;

SQL Fiddle.