在PostgreSQL上标记逻辑

时间:2015-07-16 19:10:32

标签: sql postgresql

我正在尝试在PostgreSQL上构建一个逻辑,将一些信用额度标记为“续订”。 每一行代表一个新的信用额度,续订案例或只是一个术语的变化(金额或利息,我没有在表格中显示为简单),这不被视为续订的信用额度。 将信用额度标记为续订的规则是,在原始信用额度授予日期之后至少80天或之前续订案例之后80天批准。 列'标志'显示了我想要实现的目标。 “1”表示新的信用额度或续订,“0”表示其他情况。我想使用标志来区分哪些信用额度应该用于报告(标记为0的信用额度不应报告)。 在PostgreSQL中最好的方法是什么。

+----------+-----------+-----------------------+--------+------+------+
| customer |   date    | days_after_first_line | amount | rank | flag |
+----------+-----------+-----------------------+--------+------+------+
| a        | 1/1/2015  |                     0 |    100 |    1 |    1 |
| a        | 2/28/2015 |                    58 |    150 |    2 |    0 |
| a        | 3/26/2015 |                    84 |    150 |    3 |    1 |
| a        | 4/6/2015  |                    95 |    170 |    4 |    0 |
| a        | 6/11/2015 |                   161 |    170 |    5 |    0 |
| a        | 6/17/2015 |                   167 |    200 |    6 |    1 |
| a        | 7/14/2015 |                   194 |    200 |    7 |    0 |
| a        | 9/14/2015 |                   256 |    200 |    8 |    1 |
| a        | 9/14/2015 |                   256 |    200 |    8 |    1 |
| a        | 10/5/2015 |                   277 |    200 |    9 |    0 |
| b        | 1/1/2014  |                     0 |     50 |    1 |    1 |
| b        | 3/2/2014  |                    60 |     50 |    2 |    0 |
| b        | 4/1/2014  |                    90 |     50 |    3 |    1 |
| b        | 6/15/2014 |                   165 |     80 |    4 |    0 |
| b        | 7/20/2014 |                   200 |     80 |    5 |    1 |
+----------+-----------+-----------------------+--------+------+------+

1 个答案:

答案 0 :(得分:1)

您可以使用递归查询:

WITH RECURSIVE t(customer, date, days_after_first_line, amount, rank, flag, 
                 new_flag, last_daysafter)
AS(
  SELECT customer, date, days_after_first_line, amount, rank, flag, 
         1 as new_flag,  days_after_first_line As  last_daysafter
  FROM table1
  WHERE days_after_first_line = 0
  UNION ALL
  SELECT t1.customer, t1.date, t1.days_after_first_line, t1.amount, t1.rank, t1.flag,
         CASE WHEN t1.days_after_first_line - t.last_daysafter >=80
              THEN 1 ELSE 0
         END As flag, 
         CASE WHEN t1.days_after_first_line - t.last_daysafter >=80
              THEN t1.days_after_first_line ELSE t.last_daysafter
         END As flag
  FROM table1 t1
  JOIN t ON t1.customer = t.customer AND t.rank + 1 = t1.rank
)
SELECT * FROM t
order by 1,2;

演示:http://sqlfiddle.com/#!15/bb5eb/6

在此演示中(在此查询的结果中)flag列取自数据,并计算new_flag列,因此您可以将预期结果与实际(计算的)new_flag值进行比较。