1

Blockquote

Given these requirements:

rate lookup table:

effective_start_date | effective_end_date  | amount | rate_type
----------------------------------------------------------------
2016-01-16 00:00:00  | 2016-02-15 00:00:00 |   0.10 | rate1
2016-01-16 00:00:00  | 2016-02-15 00:00:00 |    156 | rate2 (annual)
2016-02-16 00:00:00  | 2016-03-15 00:00:00 |   0.15 | rate1

input/source table:

datetime            | person | qty | x  | vatable
-------------------------------------------------
2016-01-15 00:00:00 |     p1 |  10 | x1 | Y
2016-01-16 00:00:00 |     p1 |  10 | x1 | Y
2016-01-16 00:00:00 |     p1 |  11 | x2 | N
2016-01-16 01:00:00 |     p1 |  9  | x1 | Y
2016-01-16 02:00:00 |     p2 |  10 | x1 | Y
2016-02-15 00:00:00 |     p1 |  8  | x1 | Y
2016-02-15 00:00:00 |     p1 |  8  | x2 | Y
2016-02-16 00:00:00 |     p1 |  8  | x1 | Y
2016-02-16 00:00:00 |     p1 |  7  | x2 | Y

if rate2 is used:
monthly_qty = sum of qty PER month of param (jan 16 - 31, feb 1 - 15)
calculated_rate = rate amount/12/monthly_qty
calculated_fee = calculated_rate * qty
vatable_qty = sum of qty with vatable = Y vat = calculated_rate * vatable_qty * 0.12

if param = jan 16 - feb 15 (period is bound on effective start and end date)

output table expected:

datetime            | person | qty | monthly_qty | calc_rate | calc_fee       | vat_qty | vat
--------------------------------------------------------------------------------------------------
2016-01-16 00:00:00 |     p1 | 21  | 40          | 156/12/40 | calc_rate * 21 | 10      | calc_rate * 10 * 0.12
2016-01-16 01:00:00 |     p1 | 9   | 40          | 156/12/40 | calc_rate * 9  | 9       | calc_rate * 9 * 0.12
2016-01-16 02:00:00 |     p2 | 10  | 40          | 156/12/40 | calc_rate * 10 | 10      | calc_rate * 10 * 0.12
2016-02-15 00:00:00 |     p1 | 16  | 16          | 156/12/16 | calc_rate * 16 | 16      | calc_rate * 16 * 0.12

(1) I am getting the wrong total_qty_per_month (monthly_qty) - for january, it includes 2016-01-15 in the total, actual: 50, expected: 40 (10 + 11 + 9 + 10 only)

EDIT: Here's my updated SQL: (I am using a view)

select it.datetime, it.person, 'rate2'::varchar as rate_used,
  sum(it.qty) as qty, 
  rl.amount, rl.effective_start_date, rl.effective_end_date,
  sum(sum(it.qty)) over w_month as total_qty_per_month,
  rl.amount / 12 / sum(sum(it.qty)) over w_month as calculated_rate,
  ((rl.amount / 12 / sum(sum(it.qty)) over w_month) * sum(qty)) as calculated_fee,
  sum(case when it.vatable = 'Y' then it.qty else 0 end) as vatable_qty
  from input_table it
  inner join rate_lookup_table rl on it.datetime between rl.effective_start_date and rl.effective_end_date
  where it.person_type='PT1' and rl.rate_type = 'rate2' 
  group by it.datetime, it.person, rl.amount, rl.effective_start_date, rl.effective_end_date
  window w_month as (partition by date_trunc('month', it.datetime))
  order by it.datetime

I need to get the sum of the window function based on effective_start_date and effective_end_date of the rate lookup table.

2
  • 1
    What data type is effective_date? Are that two DATE columns? And what data type is input_table.datetime? Is that a timestamp Can edit the question and add the create table statements for both tables? Commented Jan 14, 2017 at 10:10
  • 1
    they're both timestamp without time zone Commented Jan 14, 2017 at 10:51

1 Answer 1

3

As far as I can tell, you can do that using a join with between and a window function to calculate the sum per month:

select it.datetime, it.person, it.qty, rl.amount, rl.rate_type, 
       rl.amount / 12 / sum(it.qty) over (partition by date_trunc('month', it.datetime)) as calculated_rate       
from rate_lookup_table rl
  join input_table it on it.datetime between rl.effective_start_date and effective_end_date
where rl.rate_type = 'rate2';

date_trunc('month', it.datetime) "normalized" the date to the start of the month, so all values for the same month are the same. So the window function will sum up all quantities for the same month.

Based on your sample data, this returns:

datetime            | person | qty | amount | rate_type | calculated_rate
--------------------+--------+-----+--------+-----------+----------------
2016-01-16 00:00:00 | p1     |  10 |    156 | rate2     |            0.45
2016-01-16 01:00:00 | p1     |   9 |    156 | rate2     |            0.45
2016-01-16 02:00:00 | p2     |  10 |    156 | rate2     |            0.45
2016-02-15 00:00:00 | p1     |   8 |    156 | rate2     |            1.63

The calculated_fee and vat can be derived from the calculated_rate. To not repeat the expression you can use a derived table:

select *, 
       calculated_rate * qty as calculated_fee,
       calculated_rate * qty * 0.12 as vat
from (
  select it.datetime, it.person, it.qty, rl.amount, rl.rate_type, 
         rl.amount / 12 / sum(it.qty) over (partition by date_trunc('month', it.datetime)) as calculated_rate       
  from rate_lookup_table rl
    join input_table it on it.datetime between rl.effective_start_date and effective_end_date
  where rl.rate_type = 'rate2'
) t;
Sign up to request clarification or add additional context in comments.

1 Comment

updated my question as I am getting the wrong monthly_qty, and partition by date_trunc('month', it.datetime) between rl.effective_start_date and rl.effective_end_date) doesn't seem to help.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.