Re: How to distribute budget value to actual rows in Postgresql

From: David Johnston <polobo(at)yahoo(dot)com>
To: pgsql-general(at)postgresql(dot)org
Subject: Re: How to distribute budget value to actual rows in Postgresql
Date: 2014-02-09 22:23:48
Message-ID: 1391984628433-5791175.post@n5.nabble.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Andrus Moor wrote
> Budget table contains jobs with loads:
>
> create temp table budget (
> job char(20) primary key,
> load numeric(4,1) not null check (load>0 )
> );
> insert into budget values ( 'programmer', 3 );
> insert into budget values ( 'analyst', 1.5 );
>
> Actual table contains actual loads by employees:
>
> create temp table actual (
> job char(20),
> employee char(20),
> load numeric(4,1) not null check (load>0 ),
> contractdate date,
> primary key (job, employee)
> );
>
> insert into actual values ( 'programmer', 'John', 1, '2014-01-01' );
> -- half time programmer:
> insert into actual values ( 'programmer', 'Bill', 0.5, '2014-01-02' );
>
> insert into actual values ( 'analyst', 'Aldo', 1, '2014-01-03' );
> insert into actual values ( 'analyst', 'Margaret', 1, '2014-01-04' );
>
> Result table should show difference between budget and actual jobs so that
> budget load is
> distributed to employees in contract date order.

sum(...) OVER (ORDER BY)

This provides for a cumulative sum calculation using whatever order you
desire.

> If budget load is greater than sum of job loads, separate budget line with
> empty employee
> should appear.

This is a separate query that would then be added to the budget/actual query
via:

UNION ALL

> In data above, 1.5 programmers are missing and 0.5 analysts are more.
>
> Result should be
>
> Job Employee Budget Actual Difference
>
> programmer John 1 1 0
> programmer Bill 0.5 0.5 0
> programmer 1.5 0 1.5
> analyst Aldo 1 1 0
> analyst Margaret 0.5 1 -0.5
>
> How to create such table in modern Postgresql ?
> Can rank function with full join used or other idea ?

I don't get how a rank function is going to useful here...

> I tried
>
> select
> coalesce(budget.job, actual.job ) as job,
> employee,
> budget.load as budget,
> coalesce(actual.load,0) as actual,
> coalesce(budget.load,0)-coalesce( actual.load,0) as difference
> from budget full join actual on (job)
> order by contractdate
>
> but this does not distribute budget load to employee rows.

My initial reaction is that you will need at least 3 separate sub-queries to
accomplish your goal - though it may be that you have to resort to using
pl/pgsql and implement procedural logic. Pure SQL will probably be
sufficient though.

To make this easier to manage you should use CTE/WITH:

WITH sub1 AS ()
, sub2 AS ()
, sub3 AS ()
, sub4 AS ( SELECT * FROM sub2 UNION ALL sub3 )
SELECT * FROM sub4;

David J.

--
View this message in context: http://postgresql.1045698.n5.nabble.com/How-to-distribute-budget-value-to-actual-rows-in-Postgresql-tp5791170p5791175.html
Sent from the PostgreSQL - general mailing list archive at Nabble.com.

In response to

Browse pgsql-general by date

  From Date Subject
Next Message John Anderson 2014-02-09 22:48:53 Optimizing tables for known queries?
Previous Message Andrus 2014-02-09 21:03:53 How to distribute budget value to actual rows in Postgresql