Home > Mobile >  How do you allocate an amount in blank to the rest proportionately?
How do you allocate an amount in blank to the rest proportionately?

Time:10-16

I have a table with a list of markets and corresponding amounts related to those markets

Market Amount
A 10
B 30
C 50
D 10
10

I would like this $10 in the blank market to be allocated to the rest of the markets proportionately based on amounts excluding the blank market (ex. amount(A)/sum(A B C D))

The desired output is:

Market Amount
A 11
B 33
C 55
D 11

I think I can query it using multiple CTEs, but wanted to see if it's possible to allocate using as few CTEs as possible or not using CTE at all.

CodePudding user response:

So with this CTE just for data:

with data(market, amount) as (
    select * from values
    ('A',   10),
    ('B',   30),
    ('C',   50),
    ('D',   10),
    (null, 10)
)

we can:

select d.*
    ,sum(iff(d.market is null, d.amount,null)) over() as to_spread
    ,sum(iff(d.market is not null, d.amount,null)) over() as total
    ,div0(d.amount, total) as part
    ,part * to_spread as bump
    ,d.amount   bump as result
from data as d
qualify market is not null

to get:

MARKET AMOUNT TO_SPREAD TOTAL PART BUMP RESULT
A 10 10 100 0.1 1 11
B 30 10 100 0.3 3 33
C 50 10 100 0.5 5 55
D 10 10 100 0.1 1 11

We can then fold a few of those steps up:

select d.*
    ,d.amount    div0(d.amount, sum(iff(d.market is not null, d.amount,null)) over()) * sum(iff(d.market is null, d.amount,null)) over() as result
from data as d
qualify market is not null
MARKET AMOUNT RESULT
A 10 11
B 30 33
C 50 55
D 10 11

seems these results are on fixed point numbers, the truncation of division, will loss "amounts", which could be spread fairly, but that might require a second pass.

  • Related