如何使用CTE处理累积日期?

huangapple go评论51阅读模式
英文:

How can we use CTE to handle cumulative date?

问题

我想在Postgres中编写一个递归的通用表达式(CTE),用于计算累积日期,是否可能以及如何实现?<br/>
非常感谢。

这里有一个示例
如何使用CTE处理累积日期?:

| 项目 | 记录日期                  | 宽限期(天数) | 暂停日期       |
| ---- | ------------------------ | ------------------- | --------------- |
| A    | 2022-12-14 00:00:00.000  | 30                  | 2023-01-13      |
| B    | 2022-12-29 00:00:00.000  | 30                  | 2023-02-12      |
| C    | 2023-06-02 08:40:14.933  | 30                  | 2023-07-01      |
| D    | 2023-06-02 08:54:48.080  | 30                  | 2023-07-31      |
| E    | 2023-06-03 06:42:42.077  | 30                  | 2023-08-30      |

要求:
当前的暂停日期是由记录日期或上一条记录的暂停日期计算的

  1. 对于项目A,暂停日期是在记录日期之后的30天,即2023-01-13
  2. 对于项目B,由于项目A的最后暂停日期是2023-01-13,大于项目B的记录日期(项目A的暂停日期 > 项目B的记录日期),因此项目B的暂停日期将在项目A的暂停日期之后的30天计算,即2023-02-12
  3. 由于项目C的记录日期大于项目B的暂停日期,因此项目C的暂停日期将在项目C的记录日期之后的30天计算,即2023-07-01
英文:

I want to write a recursive common table expression (CTE) in postgres to calculate a cumulative date, is it possible and how? <br/>
Many thanks.

Here's an example
如何使用CTE处理累积日期?:

| Item | Recorded Date            | Grace period (days) | Suspension Date |
| ---- | ------------------------ | ------------------- | --------------- |
| A    | 2022-12-14 00:00:00.000  | 30                  | 2023-01-13      |
| B    | 2022-12-29 00:00:00.000  | 30                  | 2023-02-12      |
| C    | 2023-06-02 08:40:14.933  | 30                  | 2023-07-01      |
| D    | 2023-06-02 08:54:48.080  | 30                  | 2023-07-31      |
| E    | 2023-06-03 06:42:42.077  | 30                  | 2023-08-30      |

Requirements:
The current suspension date is to calculated by Recorded Date or last record's suspension date

  1. For item A, suspension date is calculated by 30 days after Recorded Date is 2023-01-13
  2. For Item B, since last suspension date of Item A is 2023-01-13 which is larger than recorded date of Item B (ItemA’s suspension date > ItemB’s recorded date), then itemB’s suspension date would be calculated by 30 days after ItemA’s suspension date is 2023-02-12
  3. Since ItemC’s recorded date is larger than ItemB’s suspension date, then ItemC’s suspension date would be calculated by 30 days after ItemC’s recorded date is 2023-07-01

答案1

得分: 1

使用row_number()来识别按Recorded_Date排序的行的顺序。

递归CTE将如下所示:

with 
cte as
(
   select Item, Recorded_Date, Grace_Period,
          rn = row_number() over (order by Recorded_Date)
   from   your_table
),
rcte as
(
  -- 锚定成员
  select  Item, Recorded_Date, Grace_Period,
          rn, Suspension_Date = dateadd(day, Grace_Period, Recorded_Date)
  from    cte
  where   rn = 1

  union all

  -- 递归成员
  select  c.Item, c.Recorded_Date, c.Grace_Period, c.rn,
          Suspension_Date = case when r.Suspension_Date > c.Recorded_Date
                                 then dateadd(day, c.Grace_Period, r.Suspension_Date)
                                 else dateadd(day, c.Grace_Period, c.Recorded_Date)
                                 end
  from    rcte r
          inner join cte c on r.rn + 1 = c.rn 
)
select *
from   rcte

希望这对您有所帮助。

英文:

Use a row_number() to identify the sequence of rows in the ordering of Recorded_Date

The recursive CTE will looks like

with 
cte as
(
   select Item, Recorded_Date, Grace_Period,
          rn = row_number() over (order by Recorded_Date)
   from   your_table
),
rcte as
(
  -- anchor member
  select  Item, Recorded_Date, Grace_Period,
          rn, Suspension_Date = dateadd(day, Grace_Period, Recorded_Date)
  from    cte
  where   rn = 1

  union all

  -- recursive member
  select  c.Item, c.Recorded_Date, c.Grace_Period, c.rn,
          Suspension_Date = case when r.Suspension_Date &gt; c.Recorded_Date
                                 then dateadd(day, c.Grace_Period, r.Suspension_Date)
                                 else dateadd(day, c.Grace_Period, c.Recorded_Date)
                                 end
  from    rcte r
          inner join cte c on r.rn + 1 = c.rn 
)
select *
from   rcte

huangapple
  • 本文由 发表于 2023年6月19日 11:40:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76503494.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定