【问题标题】:Conditionally use today's date or report date for the last row of each group in SQLSQL 中每个组的最后一行有条件地使用今天的日期或报告日期
【发布时间】:2021-10-29 23:46:54
【问题描述】:

我在 Redshift/PostgreSQL 中有一张报告交易的表格,我不时上传包含发票及其到期和付款日期的报告,如下所示:

invoice_Id report_date due_date paid_date
A1 08-26-2021 09-02-2021 08-25-2021
A2 08-26-2021 08-29-2021
A3 08-26-2021 09-05-2021
A4 08-26-2021 08-30-2021
A1 08-28-2021 09-02-2021 08-25-2021
A2 08-28-2021 08-29-2021
A3 08-28-2021 09-05-2021 08-27-2021
A4 08-28-2021 08-30-2021
A1 08-30-2021 09-02-2021 08-25-2021
A2 08-30-2021 08-29-2021
A3 08-30-2021 09-05-2021 08-27-2021
A4 08-30-2021 08-30-2021

我需要根据paid_date、due_date 和 (这是棘手的部分)report_date 或 TODAY,当报告是每张发票的最后一张时。

invoice_Id report_date due_date paid_date status
A1 08-26-2021 09-02-2021 08-25-2021 PAID
A2 08-26-2021 08-29-2021 PENDING
A3 08-26-2021 09-05-2021 PENDING
A4 08-26-2021 08-30-2021 PENDING
A1 08-28-2021 09-02-2021 08-25-2021 PAID
A2 08-28-2021 08-29-2021 PENDING
A3 08-28-2021 09-05-2021 08-27-2021 PAID
A4 08-28-2021 08-30-2021 PENDING
A1 08-30-2021 09-02-2021 08-25-2021 PAID
A2 08-30-2021 08-29-2021 PAST_DUE
A3 08-30-2021 09-05-2021 08-27-2021 PAID
A4 08-30-2021 08-30-2021 PENDING

假设今天是 2021 年 8 月 31 日:

invoice_Id report_date due_date paid_date status
A1 08-30-2021 09-02-2021 08-25-2021 PAID
A2 08-30-2021 08-29-2021 PAST_DUE
A3 08-30-2021 09-05-2021 08-27-2021 PAID
A4 08-30-2021 08-30-2021 PAST_DUE

如你所见:

我正在尝试类似的东西:

SELECT report_date, due_date, paid_date,
  CASE
   WHEN paid_date IS NOT NULL THEN 'PAID'
   WHEN report_date > due_date AND paid_date is null THEN 'PAST_DUE'
   WHEN report_date <= due_date THEN 'PENDING'
  END as status
FROM reported_transaction

但我需要确保每张发票报告交易的最后一行都使用交易中的今天日期。所以而不是:

   ...
   WHEN report_date > due_date AND paid_date is null THEN 'PAST_DUE'
   WHEN report_date <= due_date THEN 'PENDING'
   ...

它使用:

   ...
   WHEN get_date() > due_date THEN 'PAST_DUE'
   WHEN get_date() <= due_date THEN 'PENDING'
   ...

【问题讨论】:

  • 我删除了不一致的数据库标签。请仅使用您真正使用的数据库进行标记。
  • @alex 下面的解决方案有效吗?

标签: sql date amazon-redshift


【解决方案1】:

你可以试试这个吗?

  • 第一步是根据日期创建排名。

  • 然后获取最大排名,然后将每个 id 的最大排名与我们在第一个 CTE 中创建的每个排名列进行比较

  • 如果排名与最高排名相同,那么我们会按照您当前的数据条件进行处理,否则会按照正常条件进行处理


    WITH ranked_date as (
    
    select 
    *,
    row_number() over(partition by invoice_id order by report_date) as ranked_date
    
    from [table name]
    ),
    
    max_rank as (
    select
    invoice_id,
    max(ranked_date) as max_ranked_date
    from ranked_date
    group by 1
    )
    
    select 
    ranked_date.invoice_id,
    ranked_date.ranked_date,
    CASE 
         WHEN ranked_date.ranked_date = max_rank.max_ranked_date THEN
             CASE
                 WHEN get_date() > due_date THEN 'PAST_DUE'
                 WHEN get_date() <= due_date THEN 'PENDING'
                 END
         WHEN ranked_date.ranked_date != max_rank.max_ranked_date THEN
             CASE 
                 WHEN report_date > due_date AND paid_date is null THEN 'PAST_DUE'
                 WHEN report_date <= due_date THEN 'PENDING'
             END
    ELSE 'NO CONDITION SPECIFIED' 
    END AS new_status
    
    
    FROM ranked_date
    INNER JOIN max_rank 
    ON ranked_date.invoice_id = max_rank.invoice_id

【讨论】:

  • 感谢您的回复。我认为这是有道理的,但我仍然围绕ranked_date.ranked_date = max_rank.max_ranked_date 与ranked_date.ranked_date != max_rank.max_ranked_date 然后null 作为new_status。我尝试了我的代码但没有工作,但我认为我可能遗漏了一些东西。
  • @AlexRamirez 这些基本上是你的条件。我正在使用嵌套的 Case when 语句。由于我无法查看您的数据,因此可能存在一些语法错误,但逻辑是首先检查 max rank = rank 值是否是您每张发票的最后一个条目,因此您将有 get_date() 的条件。如果排名与最高排名不同,则表示它不是该 invoice_id 的最后一个发票条目,然后您的条件没有 get_date()
  • 如果您在没有 case 语句的情况下运行代码(将它们注释掉)并在最后一条语句中添加 max_ranked_date。你看对了排名吗?
  • @AlexRamirez 我做了一些调整以防万一,但我需要知道你的结果是什么
  • 最后,如果没有满足这样的条件,那么它会输入'NO CONDITION SPECIFIED'。如果我缺少条件,您可以根据您的用例添加它们
猜你喜欢
  • 1970-01-01
  • 2022-10-05
  • 1970-01-01
  • 2023-01-19
  • 1970-01-01
  • 1970-01-01
  • 2021-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多