SQL 多条件 CASE WHEN 问题 [第 2 部分 - 逻辑调整]
SQL Multi Conditional CASE WHEN issues [Part 2 - logic adjustments]
我有一个关于我昨天 post 提出的问题的跟进问题。今天,需要对逻辑进行更改。
示例数据 table 位于此 post 的底部。原代码是围绕以下逻辑编写的:
- 如果只有1个订单号-return订单日期
- 如果有 >1 个相似的订单号并且这些订单中有任何一个是用信用卡支付的 - return最近的用信用卡支付的订单日期
- 如果有 >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,则使用订单的时间戳
- 如果订单 = 2,其中一个是信用卡,则使用最早的信用卡订单的日期。
- 如果订单 = 2 且 none 是信用卡,请使用最近的订单日期。
- 如果订单 > 2 并且有信用卡,则使用最早的信用卡订单的日期。
- 如果订单 > 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;
我有一个关于我昨天 post 提出的问题的跟进问题。今天,需要对逻辑进行更改。
示例数据 table 位于此 post 的底部。原代码是围绕以下逻辑编写的:
- 如果只有1个订单号-return订单日期
- 如果有 >1 个相似的订单号并且这些订单中有任何一个是用信用卡支付的 - return最近的用信用卡支付的订单日期
- 如果有 >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,则使用订单的时间戳
- 如果订单 = 2,其中一个是信用卡,则使用最早的信用卡订单的日期。
- 如果订单 = 2 且 none 是信用卡,请使用最近的订单日期。
- 如果订单 > 2 并且有信用卡,则使用最早的信用卡订单的日期。
- 如果订单 > 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;