欢迎访问yhm138的博客园博客, 你可以通过 [RSS] 的方式持续关注博客更新

MyAvatar

yhm138

HelloWorld!

【Leetcode 2474. 购买量严格增加的客户】[MySQL 用户变量/Pandas]面向过程编程解决严格递增连续子序列问题

题目地址

https://leetcode.cn/problems/customers-with-strictly-increasing-purchases/description/

MySQL代码

# Write your MySQL query statement below

with t1 as(
    select customer_id, year(order_date) as my_year
    , sum(price) as total_spend
    from Orders
    group by customer_id,my_year
)
,
t2 as(
    select
    *

    # --------------------------只需要改动这里的逻辑,其他不要动。注意里面的语句是“顺序执行的”----------------------
    
    -- 如果customer_id切换了
    ,(case when @prev_customer_id is null or @prev_customer_id<>customer_id  then @reg:=0 end)
    ,(case when @prev_customer_id is null or @prev_customer_id<>customer_id  then @prev_total_spend:=0 end)
    ,(case when @prev_customer_id is null or @prev_customer_id<>customer_id  then @prev_my_year:= my_year - 1 end)  -- 当前年的上一年,哨兵
    
    , @prev_my_year as prev_my_year  -- 没啥用,纯粹调试用的,看这个用户变量@prev_my_year是否符合预期。



    -- 年购买量严格增加的年数(连续年)该任务是否成功,ok不一定成功,failure一定是失败了
    ,(case when total_spend>@prev_total_spend and @prev_my_year + 1 =my_year then "flag=ok" else "flag=failure" end) as flag

    -- 这是维护一个【严格递增连续子序列的长度】
    ,(case when total_spend>@prev_total_spend and @prev_my_year + 1 =my_year then @reg:=@reg+1 else @reg:=1 end)

    ,@reg as reg   -- 没啥用,纯粹调试用的,看这个用户变量@reg是否符合预期。



    -- 准备好处理下一行了,一些@prev_*用户变量更新一下
    ,@prev_total_spend:=total_spend
    ,@prev_customer_id:=customer_id
    ,@prev_my_year:=my_year

    # --------------------------只需要改动这里的逻辑,其他不要动。注意里面的语句是“顺序执行的”----------------------

    from (select * from t1 order by  customer_id asc, my_year asc ) soerted_t1,
    (select @reg := 0    -- 某用户年购买量严格增加的年数(连续年)
    ,@prev_total_spend:=0  ,@prev_customer_id := null, @prev_my_year :=null ) vars
)



select distinct customer_id
from t2
where customer_id not in (select customer_id from t2 where flag="flag=failure")
order by customer_id asc, my_year asc 


-- 下面注释掉的代码是用来调试的
# select 
# customer_id,my_year,reg,total_spend,prev_my_year,flag
# from t2
# where customer_id=6
# order by customer_id asc, my_year asc 

等效pandas代码

import pandas as pd

def find_specific_customers(orders: pd.DataFrame) -> pd.DataFrame:
    # First, we mimic the 't1' CTE by grouping and summing the price per customer per year
    orders['my_year'] = pd.DatetimeIndex(orders['order_date']).year
    t1 = orders.groupby(['customer_id', 'my_year'], as_index=False)['price'].sum().rename(columns={'price': 'total_spend'})
    
    # Sort the DataFrame similarly to the 'soerted_t1' in the query
    t1_sorted = t1.sort_values(by=['customer_id', 'my_year'])
    
    # Now we need to perform the logic that's done in 't2' CTE
    # We will use the shift operation to compare the current row with the previous one
    t1_sorted['prev_customer_id'] = t1_sorted['customer_id'].shift(1)
    t1_sorted['prev_my_year'] = t1_sorted['my_year'].shift(1)
    t1_sorted['prev_total_spend'] = t1_sorted['total_spend'].shift(1)
    
    # Initialize the reg (registration) to track the strictly increasing sequence length
    t1_sorted['reg'] = 1
    t1_sorted['flag'] = 'flag=ok'
    
    # Loop through the DataFrame to calculate conditional variables
    for i in range(1, len(t1_sorted)):
        row = t1_sorted.iloc[i]
        prev_row = t1_sorted.iloc[i - 1]
        
        if row['customer_id'] == prev_row['customer_id']:
            if row['total_spend'] > prev_row['total_spend'] and row['prev_my_year'] + 1 == row['my_year']:
                t1_sorted.at[i, 'reg'] = prev_row['reg'] + 1
            else:
                t1_sorted.at[i, 'flag'] = 'flag=failure'
                t1_sorted.at[i, 'reg'] = 1

    # Identify customers with no 'flag=failure'
    customers_without_failure = t1_sorted[~t1_sorted['customer_id'].isin(t1_sorted.loc[t1_sorted['flag'] == 'flag=failure', 'customer_id'])]['customer_id'].unique()
    
    # Return a DataFrame with the customer_id's that meet the criteria
    result = pd.DataFrame({'customer_id': customers_without_failure})
    
    return result.sort_values('customer_id').reset_index(drop=True)
posted @ 2024-01-13 15:57  yhm138  阅读(11)  评论(0编辑  收藏  举报