如何使用 Postgres 按比例将数据分配到组中?

How can I proportionally distribute data into groups using Postgres?

我有一个 Postgres table,其中包含人们的姓名、年龄以及他们拥有的弹珠数量。为简单起见,该示例只有两行,但可以更多。

name age marbles
Alice 4 10
Bob 7 20

我想检索每个年龄组的弹珠数,其中弹珠数分配给每个年龄组,与人的年龄成比例1。年龄组可能不同,但在查询时已知2.

输出将如下所示:

age_group marbles
0 2 (1/5 of Alice's marbles)
5 20 (4/5 of Alice's marbles, 3/5 of Bob's marbles)
10 8 (2/5 of Bob's marbles)

是否有一种优雅的方式来查询我的 table 以实现此目的?


1具体来说,一个人每个年龄段弹珠的比例为:

marbles_higher_age_group = (age - lower_age_group) / (higher_age_group - lower_age_group) * marbles
marbles_lower_age_group = marbles - marbles_higher_age_group

2当查询table时,年龄段是已知的。它们可以在多个查询中有所不同,并且可以任意选择。例如,一个查询可能使用年龄组 [0,5,10],而下一个查询使用 [0,1,4,8,12].

对于存储在 table

中的任意一组年龄组
select ag, sum(agm) marbles
from marbles m
join ( 
    select age_group low, lead(age_group) over(order by age_group) high
    from age_groups ag
) a on a.high >= m.age and a.low <= m.age
, lateral (
    select a.low ag , 1.0 * m.marbles * (a.high - m.age)/(a.high -  a.low) agm
    union all
    select a.high, 1.0 * m.marbles * (m.age -  a.low)/(a.high -  a.low)

) mm
group by ag
order by ag;

或者,您可以在查询中提供一组年龄组

select ag, sum(agm) marbles
from marbles m
join ( 
    select age_group low, lead(age_group) over(order by age_group) high
    from unnest(array[1,2,4,8,12]) age_groups(age_group)
) a on a.high >= m.age and a.low <= m.age
, lateral (
    select a.low ag, 1.0 * m.marbles * (a.high - m.age)/(a.high - a.low) agm
    union all
    select a.high, 1.0 * m.marbles * (m.age - a.low)/(a.high - a.low)
) mm
group by ag
order by ag;