SQL 多条件 CASE WHEN 问题 [第 2 部分 - 逻辑调整]

SQL Multi Conditional CASE WHEN issues [Part 2 - logic adjustments]

我有一个关于我昨天 post 提出的问题的跟进问题。今天,需要对逻辑进行更改。

示例数据 table 位于此 post 的底部。原代码是围绕以下逻辑编写的:

  1. 如果只有1个订单号-return订单日期
  2. 如果有 >1 个相似的订单号并且这些订单中有任何一个是用信用卡支付的 - return最近的用信用卡支付的订单日期
  3. 如果有 >1 个相似的订单号并且 none 的订单是使用信用卡支付的 - return 最近的订单日期。

感谢用户 Gordon Linoff,他提供了以下完美运行的代码:

    select o.*
from (select o.*,
             row_number() over (partition by order_number
                                order by (case when payment_method = 'Credit Card' then 1 else 2 end),
                                         order_date desc
                               ) as seqnum
      from orders o
     ) o
where seqnum = 1;

逻辑中的要求已更新,已扩展为以下内容:

  1. 如果订单数 = 1,则使用订单的时间戳
  2. 如果订单 = 2,其中一个是信用卡,则使用最早的信用卡订单的日期。
  3. 如果订单 = 2 且 none 是信用卡,请使用最近的订单日期。
  4. 如果订单 > 2 并且有信用卡,则使用最早的信用卡订单的日期。
  5. 如果订单 > 2 且 none 是信用卡,请使用最旧的订单日期。

可以通过修改Gordon 代码中的CASE WHEN 来实现吗?或者它需要的不仅仅是这么简单的改变。

原始数据 Table 有问题:

Order Number Payment Method Order Date
120 Cash 01/01/2021
175 Credit Card 01/02/2021
209 Cash 01/03/2021
209 Credit Card 01/04/2021
209 Personal Check 01/05/2021
209 Credit Card 01/06/2021
209 Cash 01/07/2021
209 Personal Check 01/08/2021
277 Credit Card 01/09/2021
301 Cash 01/10/2021
333 Personal Check 01/11/2021
333 Cash 01/12/2021
333 Cash 01/13/2021
333 Personal Check 01/14/2021
400 Credit Card 01/15/2021
551 Credit Card 01/16/2021
551 Cash 01/17/2021
680 Personal Check 01/18/2021

如果我正确理解这个逻辑,它是:

  • 取最早的订单日期,如果有信用卡的话。
  • 取最新的订单日期,如果恰好有两个订单且没有信用卡。
  • 否则,取最早的订单日期。

您可以使用另一个子查询和window函数来获取辅助信息:

select o.*
from (select o.*,
             row_number() over (partition by order_number
                                order by (case when cnt = 2 and num_cc = 0 then order_date end) desc,
                                         order_date asc
                               ) as seqnum
      from (select o.*,
                   count(*) over (partition by order_number) as cnt,
                   sum(case when payment_method = 'Credit Card' then 1 else 0 end) over (partition by order_number) as num_cc
            from orders o
           ) o
     ) o
where seqnum = 1;