如何使用 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;
我有一个 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;