简体   繁体   English

SQL窗口函数过滤

[英]SQL window function filtering

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: 如果使用rate2:
monthly_qty = sum of qty PER month of param (jan 16 - 31, feb 1 - 15) month_qty =每月PER参数数量的总和(1月16日至31日,2月1日至15日)
calculated_rate = rate amount/12/monthly_qty 计算利率=利率金额/ 12 / monthly_qty
calculated_fee = calculated_rate * qty 计算费用=计算费用*数量
vatable_qty = sum of qty with vatable = Y vat = calculated_rate * vatable_qty * 0.12 vatable_qty =数量与vatable = Y的总和vat =计算速率* vatable_qty * 0.12

if param = jan 16 - feb 15 (period is bound on effective start and end date) 如果param = 1月16日-2月15日(期限自有效开始日期和结束日期开始计算)

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) (1)我收到错误的total_qty_per_monthtotal_qty_per_month )-一total_qty_per_month ,总计包括2016-01-15,实际:50,预期:40(仅10 + 11 + 9 + 10)

EDIT: Here's my updated SQL: ( I am using a view ) 编辑:这是我更新的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

I need to get the sum of the window function based on effective_start_date and effective_end_date of the rate lookup table . 我需要基于rate lookup table effective_start_dateeffective_end_date获取窗口函数的总和。

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: 据我所知,您可以使用with和window函数 between联接来计算每月的总和:

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. date_trunc('month', it.datetime)将日期“标准化”到月初,因此同一个月的所有值都相同。 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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM