【问题标题】:How to do a conditional max to return the last purchase from the customer for each warranty claim?对于每个保修索赔,如何进行有条件的最大退货以从客户那里退回最后一次购买?
【发布时间】:2021-02-22 06:26:27
【问题描述】:

您好,我有一个如下所示的数据表

OrderID Date Product Name CustomerID
476070 February 24,2021 WARRANTY CLAIM ABC123
476069 February 22,2021 PRODUCT C ABC123
476068 February 10,2021 WARRANTY CLAIM ABC123
476067 February 1,2021 WARRANTY CLAIM ABC123
476064 January 23,2021 PRODUCT B ABC123
476051 January 10,2021 WARRANTY CLAIM ABC123
475023 January 1 , 2021 PRODUCT A ABC123

我想要实现的是对于每个保修索赔,我想获得该客户的最后一次产品购买。

所以意思就是我想要达到的输出是这样的

OrderID Date Product Name CustomerID LASTPRODUCTPURCHASE
476070 February 24,2021 WARRANTY CLAIM ABC123 PRODUCT C
476069 February 22,2021 PRODUCT C ABC123 NULL
476068 February 10,2021 WARRANTY CLAIM ABC123 PRODUCT B
476067 February 1,2021 WARRANTY CLAIM ABC123 PRODUCT B
476064 January 23,2021 PRODUCT B ABC123 NULL
476051 January 10,2021 WARRANTY CLAIM ABC123 PRODUCT A
475023 January 1 , 2021 PRODUCT A ABC123 NULL

我已经尝试过 LAG 和 MAXIF,但它会返回该特定客户的先前订单或最新订单。我需要该客户的LAST产品购买,并且仅适用于保修索赔订单。

我正在为 CTE 解决方案获取此输出

这是我运行的查询:

WITH cte AS (
    SELECT *, MAX(CASE WHEN productName <> 'Warranty Service' OR productName <> 'Warranty Collect' OR productName <> 'Warranty Inspection' OR productName <> 'Delivery' THEN id END) OVER
                  (PARTITION BY vpn ORDER BY ordercompleted_at) MaxOrderID
    FROM baterikudatawarehouse.bateriku_production.BaterikuOrderTrafficJune2020
    where orderStatus = 'completed' and vpn = 'QMY70' order by ordercompleted_at DESC
)

SELECT t1.id ,t1.ordercompleted_at, t1.productName, t1.vpn,
       CASE WHEN t1.productName = 'Warranty Service' OR t1.productName = 'Warranty Collect' OR t1.productName = 'Delivery' OR t1.productName = 'Warranty Inspection'
            THEN t2.productName END AS LASTPRODUCTPURCHASE
FROM cte t1

INNER JOIN baterikudatawarehouse.bateriku_production.BaterikuOrderTrafficJune2020 t2
    ON t2.vpn = t1.vpn AND
       t2.id = t1.MaxOrderId ORDER BY t1.ordercompleted_at DESC;

【问题讨论】:

    标签: sql postgresql google-bigquery


    【解决方案1】:

    这是使用lead 的另一种方法:

    select orderid,Date,productname,customerid,
           case when productname = 'WARRANTY CLAIM' then
           max(lastpn)over(partition by customerid order by orderid) else null end as LASTPRODUCTPURCHASE 
           from (
                 select tb.*, 
                 case when lead(productname)over(partition by customerid order by OrderID desc) = 'WARRANTY CLAIM' then null 
                 else lead(productname)over(partition by customerid order by OrderID desc) end as lastpn
                 from tb
                ) a
    

    这里是db<>fiddle,包括@Tim Biegeleisen 答案,如果允许 CTE,IMO 会更好地选择。
    我还在 dbfiddle 中添加了更多带有示例数据的行以便更好地检查。

    【讨论】:

    • 这行得通!非常感谢。由于此查询使用了铅,因此有什么注意事项吗?
    • @SyedAriff 实际上我想不出它会发生什么问题,我想唯一需要注意的是order by,确保数据遵循正确的顺序。
    【解决方案2】:

    一种方法,首先在每个时间点找到每个客户的最新订单:

    WITH cte AS (
        SELECT *, MAX(CASE WHEN ProductName <> 'WARRANTY CLAIM' THEN OrderID END) OVER
                      (PARTITION BY CustomerID ORDER BY Date) MaxOrderID
        FROM yourTable
    )
    
    SELECT t1.OrderID, t1.Date, t1.ProductName, t1.CustomerID,
           CASE WHEN t1.ProductName = 'Warranty Claim'
                THEN t2.ProductName END AS LASTPRODUCTPURCHASE
    FROM cte t1
    INNER JOIN yourTable t2
        ON t2.CustomerID = t1.CustomerID AND
           t2.OrderID = t1.MaxOrderId;
    

    请注意,返回原始表的连接会从最近的非保修事务中提取最新的产品名称。

    【讨论】:

    • 非常感谢您能在这个答案中加入小提琴
    • 我现在在手机上,上面的代码还没有测试过。
    • 好的,我已经尝试过了,但它似乎不起作用。保修索赔在 LASTPRODUCTPURCHASE 列中返回保修索赔
    • @TimBiegeleisen 注意区分大小写。
    • 我在问题中发布了上述查询的输出
    猜你喜欢
    • 2013-03-14
    • 1970-01-01
    • 1970-01-01
    • 2021-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-18
    • 1970-01-01
    相关资源
    最近更新 更多