块引用
鉴于这些要求:
速率查找表:

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

输入/源表:
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

如果使用rate2:
每月数量=参数每月数量之和(1月16日-31日,2月1日-15日)
计算单价=单价金额/12/月单价
计算费用=计算费率*数量
增值税数量=增值税数量之和=Y
增值税=计算税率*可增值数量*0.12
如果param=1月16日-2月15日(期间以有效开始和结束日期为界)
需要输出表:
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)我弄错了total_qty_per_month(每月数量)-1月份,总共包括2016-01-15,实际:50,预期:40(仅10+11+9+10)
编辑:这是我更新的SQL:(我正在使用一个视图)
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

我需要得到基于effective_start_dateeffective_end_date的窗口函数的和。

最佳答案

据我所知,您可以使用join withbetween和awindow function来计算每月的总和:

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”到月初的日期,因此同一个月的所有值都相同。因此窗口函数将汇总同一个月的所有数量。
根据您的样本数据,这将返回:
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

计算出的费用和增值税可以从计算出的税率中得出。要不重复表达式,可以使用派生表:
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;

09-05 16:17