给定开始日期和结束日期的按天预计付款

Expected payments by day given start and end date

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

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

目前,我不需要担心工作日与日历日的关系。

在其最简单的形式中,最终结果将包含每个历史日历日以及下一年的未来日期,并得出在这些特定日期预计会收到多少was/is。

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

期望的输出看起来像这样:

| 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

免责声明:我不是 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(通用 Table 表达式)的数量最多产生 9999 天。如果您需要更长的承诺,请用第五位展开。

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

是这样的,不过我没用过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

本质上,我们将循环 table 几次笛卡尔连接在一起以生成大量行,对它们进行编号并将数字添加到最小日期以获得递增日期系列。

付款数据 table 加入到这个递增的日期系列中:

  • (系列日期的那一天)= monthlies
  • (付款日)
  • (系列日期的月-日)=(start_date 的月份和付款日)

最后对整批进行分组求和

我没有 Netezza 的测试实例,所以如果您遇到一些小的语法错误,请尝试自己修复它们(以便您更快地获得解决方案)。如果您无法弄清楚查询在做什么,请告诉我