给定日期记录和间隔 30 天的第一个记录获取上一个计费周期

Get The Previous Billing Cycle Given The Date Record And First Record With A 30-day Interval

我正在尝试通过给定两个值来获取之前的结算周期:

  1. 首次记录日期
  2. 给定记录日期

鉴于上一个计费周期应在第一个记录日期的 30 天间隔内,我如何获得上一个计费周期?这里有一个 table 让您了解我在说什么:

|======================|======================|======================|
| first_record_date    | date_recorded        | prev_bill_cycle      |
|======================|======================|======================|
| 2021-06-30           | 2021-11-15           | 2021-10-30           |
| 2021-06-15           | 2021-09-16           | 2021-09-15           |
| 2021-09-15           | 2021-09-16           | 2021-09-15           |
| 2021-06-30           | 2022-01-05           | 2021-12-30           |
| 2021-11-30           | 2022-11-31           | 2021-11-30           |
| 2020-02-29           | 2022-01-31           | 2022-01-29           |
| 2020-02-29           | 2022-01-31           | 2022-01-29           |
| 2020-02-29           | 2022-02-28           | 2022-02-28           |
| 2021-01-05           | 2022-01-03           | 2021-12-05           |
| 2021-01-05           | 2022-01-07           | 2022-01-05           |
|======================|======================|======================|

一些注意事项:

这是我目前得到的结果:

SELECT
  first_record,
  record_date,
  (
    CASE
      WHEN date_recorded::DATE <= first_record::DATE THEN first_record_date
      WHEN date_recorded::DATE - INTERVAL '30 day' <= first_recorded_date::DATE THEN first_recorded_date
      WHEN date_recorded::DATE - INTERVAL '30 day' > CONCAT(TO_CHAR(date_recorded,'YYYY-MM-'),TO_CHAR(first_recorded_date,'DD'))::DATE
        THEN CONCAT(TO_CHAR(date_recorded,'YYYY-MM-'),TO_CHAR(first_recorded_date,'DD'))::DATE
      WHEN date_recorded::DATE - INTERVAL '30 day' > first_recorded_date::DATE THEN date_recorded
      ELSE date_recorded::DATE
    END
  )AS previous_billing_cycle
FROM records_table

我遇到了闰年问题,或者日期与 first_record_date 日期不匹配。例如,有些月份没有第 31 天。

这是 DB-Fiddle 中的示例:https://www.db-fiddle.com/f/rZcgNiB9Nrt2PgVm2WnywA/5

我意识到使用 CASE/IF 语句是行不通的,因为自 first_record_date.

以来的 30 个间隔天的计算不一定匹配

代码如下:

SELECT
  first_record_date,
  date_recorded,
  DATE_PART('day', (first_record_date::DATE + INTERVAL '90 day') - first_record_date::DATE) AS first_and_next_cycle_date,
  date_recorded::DATE - first_record_date::DATE AS date_recorded_minus_first_record,
  (date_recorded::DATE - first_record_date::DATE)::INTEGER / 30 AS multiplier,
  DATE_PART('day', (first_record_date::DATE + INTERVAL '30 day' * ((date_recorded::DATE - first_record_date::DATE)::INTEGER / 30)) - first_record_date::DATE) AS additional_days,
  first_record_date::DATE + INTERVAL '1 day' * DATE_PART('day', (first_record_date::DATE + INTERVAL '30 day' * ((date_recorded::DATE - first_record_date::DATE)::INTEGER / 30)) - first_record_date::DATE) AS previous_billing_cycle,
  first_record_date::DATE + INTERVAL '1 day' * DATE_PART('day', (first_record_date::DATE + INTERVAL '30 day' * (((date_recorded::DATE - first_record_date::DATE)::INTEGER / 30) + 1)) - first_record_date::DATE) AS end_billing_cycle
FROM records

数据库 fiddle 中的答案如下: https://www.db-fiddle.com/f/rZcgNiB9Nrt2PgVm2WnywA/9