根据前一列计算得出的列

时间:2019-07-20 07:09:22

标签: sql postgresql

我们有一个表A

amount numeric,
serial int,
due_date date,
rate numeric,
mi numeric

样本数据:

amount.   rate.  due_date       mi.     serial
100000.   0.012.  '2017-01-01'   3000.    1
100000.   0.012.  '2017-02-01'   3000.    2
100000    0.012.  '2017-03-01'.  2000.    3
.
.
.

金额列和行之间的比率是恒定的。

我想为表的每一行构造一个视图,如下所示:

serial  opening      int_amount.  prncpl_amount.         prncpl_os
1.      amount          opening*0.012    mi-int_amount.   opening-prncpl_amount
2. previous(prncpl_os)  opening*0.012.   mi-int_amount.    opening-prncpl_amount       
.
.

我尝试使用滞后函数,但是由于prncpl_os不存在,因此失败。

编辑1:所需的结果将是

serial.    opening.    int_amount.    prncpl_amount.  prncpl_os
1.         100000.      1200           1800          98200
2.         98200.       1178.40.       1821.60.      96378.40
3.         96378.40.    1156.54.       843.46.       95534.94

编辑2:计算错误已按要求纠正...

1 个答案:

答案 0 :(得分:3)

您需要一个recursive CTE

demo:db<>fiddle

WITH RECURSIVE next_ser AS (
    SELECT 
        a.*,
        lead(serial) OVER (ORDER BY serial) as next_serial
    FROM a
),
cte AS (

    SELECT
        serial,
        next_serial,
        amount AS opening,
        amount * rate AS int_amount,
        mi - (amount * rate) AS prncpl_amount,
        amount - mi + amount * rate AS prncpl_os
    FROM
        next_ser
    WHERE serial = 1

    UNION ALL

    SELECT
        a.serial,
        a.next_serial,
        c.prncpl_os,
        c.prncpl_os * a.rate,
        a.mi - (c.prncpl_os * rate),
        c.prncpl_os - mi + c.prncpl_os * rate
    FROM next_ser a
    JOIN cte c ON a.serial = c.next_serial
)
SELECT 
    serial, opening, int_amount, prncpl_amount, prncpl_os
FROM cte
  1. next_ser CTE用于在lead() window function的帮助下计算下一个序列(如果它们不是真正连续的),
  2. 递归很简单:非递归部分(SELECT的第一个UNION语句)是起点,它将计算您的第一行。 UNION的第二部分是CTE的递归部分。在该行中,最后一个递归步骤(JOIN cte)与serial id等于最后一个递归步骤的next_serial的行结合在一起。先前的prncpl_os值可以当作是使用当前值来计算的...