在给定的开始日期和结束日期之前的预期付款

时间:2019-01-04 18:51:20

标签: sql netezza recurring-events

我正在尝试创建一个SQL视图,该视图为我提供预期在日历日收到的定期交易金额。我有一个包含经常性承诺数据的表,其中包含以下列:

id, 
start_date, 
end_date (null if still active), 
payment day (1,2,3,etc.), 
frequency (monthly, quarterly, semi-annually, annually), 
commitment amount

就目前而言,我不必担心工作日和日历日。

以最简单的形式,最终结果将包含每个历史日历日以及下一年的未来日期,并产生在那些特定日期预期收到的/预计收到的数量。

我已经做了很多研究,但似乎找不到解决特定问题的答案。从何处开始的任何方向将不胜感激。

期望输出看起来像这样:

| Date    | Expected Amount |

|1/1/18   |  100  | 
|1/2/18   |  200  | 
|1/3/18   |  150  | 

提前谢谢您!

Link to data table in db-fiddle
Expected Output Spreadsheet

2 个答案:

答案 0 :(得分:1)

类似这样,但我从未使用过Netezza

SELECT 
  cal.d, sum(r.amount) as expected_amount
FROM
  (
    SELECT MIN(a.start_date) + ROW_NUMBER() OVER(ORDER BY NULL) as d
    FROM recurring a, recurring b, recurring c
  )  cal 
  LEFT JOIN
  recurring r
  ON 
    (
     (r.frequency = 'monthly' AND r.payment_day = DATE_PART('DAY', cal.d)) OR 
     (r.frequency = 'annually' AND DATE_PART('MONTH', cal.d) = DATE_PART('MONTH', r.start_date) AND r.payment_day = DATE_PART('DAY', cal.d))
    ) AND 
    r.start_date >= cal.d AND 
    (r.end_date <= cal.d OR r.end_date IS NULL)
GROUP BY cal.d

从本质上讲,我们笛卡尔式地将循环表连接在一起几次以生成行的负载,对行进行编号,然后将数字加到最小日期上以获得递增的日期序列。

付款数据表在以下日期与该递增日期序列保持连接:

  • (系列日期中的日期)=(每月的付款日)
  • (系列中日期的月-日)=(开始日期的月和支付日)

最后,将整个批次分组并加起来

我没有Netezza的测试实例,因此,如果您遇到一些较小的语法错误,请务必自行修复(以更快地获得解决方案)。如果您无法确定查询正在执行的操作,请告诉我

答案 1 :(得分:0)

免责声明:我不是Netezza的专家,所以我决定为您编写一个标准 SQL,可能需要进行一些调整才能在Netezza上运行。

with
digit as (select 0 as x union select 1 union select 2 union select 3 union select 4
    union select 5 union select 6 union select 7 union select 8 union select 9
),
number as ( -- produces numbers from 0 to 9999 (28 years)
  select d1.x + d2.x * 10 + d3.x * 100 + d4.x * 1000 as n
  from digit d1
  cross join digit d2
  cross join digit d3
  cross join digit d4
),
expected_payment as ( -- expands all expected payments
  select
    c.start_date + nb.n as day,
    c.committed_amount
  from recurring_commitement c
  cross join number nb
  where c.start_date + nb.n <= c.end_data
    and c.frequency ... -- add logic for monthly, quarterly, etc. here
)
select
  day,
  sum(committed_amout) as expected_amount
from expected_payment
group by day
order by day

此解决方案对于不超过28年的承诺有效,因为CTE(公用表表达式)的数量最多可产生9999天。如果您需要更长的承诺时间,请用第五位数字扩展。

注意:在Netezza的SQL中,我认为将日期添加到日期的方式是不正确的。表达式c.start_date + nb.n可能需要改写。