首页 > 数据库 >【LeetCode1747. 应该被禁止的 Leetflex 账户】[MySQL 用户变量/Pandas]面向过程编程;尝试维护一个multiset

【LeetCode1747. 应该被禁止的 Leetflex 账户】[MySQL 用户变量/Pandas]面向过程编程;尝试维护一个multiset

时间:2024-01-22 10:07:36浏览次数:25  
标签:count account ip online Leetflex ips LeetCode1747 MySQL id

目录

  • 题目地址
  • MySQL代码
  • 等效pandas代码

题目地址

https://leetcode.cn/problems/leetflex-banned-accounts/description/

MySQL代码

with t1 as(
    select account_id,ip_address,
    login as tick,
    "login" as mytype
    from LogInfo
    union all
    select account_id,ip_address,
    logout as tick,
    "logout" as mytype
    from LogInfo
)
,
t2 as(
    SELECT 
        t.*,

        # ----只需要改动这里的逻辑,其他不要动-----------
        @prev_online_ips := @online_ips,   -- 本次事件发生之前的online_ips,存一下
        @search_for := CONCAT(',', t.ip_address) as search_for,  -- 声明一个变量,存一下经常要用到的东西,尝试使代码简洁
        @first_occurrence := LOCATE(@search_for, @online_ips) as first_occurrence, -- 声明一个变量,存一下经常要用到的东西,尝试使代码简洁


        @online_ips := (case when account_id=@prev_account_id then
            (CASE 
            WHEN t.mytype = 'login' THEN CONCAT_WS(',', @online_ips, t.ip_address)
            WHEN t.mytype = 'logout' THEN 

            (CASE
                WHEN @first_occurrence > 0 THEN -- 找到第一个匹配的ip,移除它
                    CONCAT(
                        SUBSTRING(@online_ips, 1, @first_occurrence - 1), 
                        SUBSTRING(@online_ips, @first_occurrence + LENGTH(@search_for))
                    )
                ELSE
                    @online_ips
            END)

            ELSE @online_ips END)
        else (CASE 
            WHEN t.mytype = 'login' THEN CONCAT_WS(',', '', t.ip_address)
            WHEN t.mytype = 'logout' THEN 

            (CASE
                WHEN @first_occurrence > 0 THEN -- 找到第一个匹配的ip,移除它
                    CONCAT(
                        SUBSTRING(@online_ips, 1, @first_occurrence - 1), 
                        SUBSTRING(@online_ips, @first_occurrence + LENGTH(@search_for))
                    )
                ELSE
                    @online_ips
            END)

            ELSE @online_ips END)
        end) AS dummy -- This is a dummy column to update the @online_ips variable

        ,

        @online_count := 
        (case when account_id=@prev_account_id then 
            (CASE 
            WHEN t.mytype = 'login'  THEN  
                (case when FIND_IN_SET(t.ip_address, @online_ips) > 0 and FIND_IN_SET(t.ip_address, @prev_online_ips) = 0
                    then @online_count+1
                    else @online_count
                end)
            WHEN t.mytype = 'logout' THEN
                (case when FIND_IN_SET(t.ip_address, @online_ips) = 0 and FIND_IN_SET(t.ip_address, @prev_online_ips) > 0  
                  then @online_count-1
                    else @online_count
                end)
            ELSE @online_count END)
         else (CASE 
            WHEN t.mytype = 'login'  THEN  1
            WHEN t.mytype = 'logout' THEN 
                (case when FIND_IN_SET(t.ip_address, @online_ips) = 0 and FIND_IN_SET(t.ip_address, @prev_online_ips) > 0  
                    then @online_count-1
                        else @online_count
                end)
            ELSE @online_count END)
        end )
        
        AS online_ip_count

        , @prev_account_id := account_id

        # ----只需要改动这里的逻辑,其他不要动-----------
    FROM 
        (SELECT @online_ips := '', @online_ip_count := 0, @prev_account_id := null) vars,
        (SELECT * FROM t1 ORDER BY account_id asc, tick ASC) t
)


select 
distinct account_id 
from t2
where online_ip_count>=2
order by account_id asc, tick ASC

等效pandas代码

import pandas as pd
from collections import Counter

def leetflex_banned_accnts(log_info: pd.DataFrame) -> pd.DataFrame:
    login_df = log_info[['account_id', 'ip_address', 'login']].rename(columns={'login': 'tick'})
    login_df['mytype'] = 'login'
    logout_df = log_info[['account_id', 'ip_address', 'logout']].rename(columns={'logout': 'tick'})
    logout_df['mytype'] = 'logout'
    
    events = pd.concat([login_df, logout_df])
    events.sort_values(by=['account_id', 'tick'], inplace=True)
    
    # Initialize the state dictionaries
    account_ips = {}
    account_online_counts = {}
    
    # Record of banned accounts
    banned_accounts = set()
    
    for _, row in events.iterrows():
        acc_id = row['account_id']
        ip = row['ip_address']
        event_type = row['mytype']
        
        if acc_id not in account_ips:
            account_ips[acc_id] = Counter()
            account_online_counts[acc_id] = 0
        
        if event_type == 'login':
            account_ips[acc_id][ip] += 1
            # We only increase the count of online IPs if this IP wasn't already counted
            if account_ips[acc_id][ip] == 1:
                account_online_counts[acc_id] += 1
            # Check if there are 2 or more unique IPs for the current account
            if account_online_counts[acc_id] >= 2:
                banned_accounts.add(acc_id)
        else:  # logout
            if account_ips[acc_id][ip] > 0:
                account_ips[acc_id][ip] -= 1
                # We only decrease the count of online IPs if this IP is completely logged out
                if account_ips[acc_id][ip] == 0:
                    account_online_counts[acc_id] -= 1
    
    # Convert set of banned accounts to DataFrame
    banned_accounts_df = pd.DataFrame({'account_id': list(banned_accounts)})
    return banned_accounts_df.sort_values(by='account_id')



标签:count,account,ip,online,Leetflex,ips,LeetCode1747,MySQL,id
From: https://blog.51cto.com/u_15247503/9360640

相关文章

  • 【LeetCode 2701. 连续递增交易】[MySQL 用户变量/Pandas]面向过程编程得到严格递增连
    目录题目地址MySQL代码等效pandas代码题目地址https://leetcode.cn/problems/consecutive-transactions-with-increasing-amounts/MySQL代码#WriteyourMySQLquerystatementbelowwitht1as(select*#--------------------------只需要改动这里的逻辑,其他......
  • 【Leetcode1949. 坚定的友谊】使用MySQL在无向图中寻找{"CompleteTripartite", {1, 1,
    目录题目地址思路代码MySQL代码逐行翻译为Pandas代码等效Cypher查询(未验证)题目地址https://leetcode.cn/problems/strong-friendship/思路就是在无向图中寻找这个pattern:(*Mathematica*)GraphData[{"CompleteTripartite",{1,1,3}}]SQL写还是比较麻烦。更加复杂的查询还是......
  • 【Leetcode 2474. 购买量严格增加的客户】[MySQL 用户变量/Pandas]面向过程编程解决严
    目录题目地址MySQL代码等效pandas代码题目地址https://leetcode.cn/problems/customers-with-strictly-increasing-purchases/description/MySQL代码#WriteyourMySQLquerystatementbelowwitht1as(selectcustomer_id,year(order_date)asmy_year,sum(price)......
  • [转帖]MySQL多版本并发控制机制(MVCC)-源码浅析
    https://zhuanlan.zhihu.com/p/144682180 MySQL多版本并发控制机制(MVCC)-源码浅析前言作为一个数据库爱好者,自己动手写过简单的SQL解析器以及存储引擎,但感觉还是不够过瘾。<<事务处理-概念与技术>>诚然讲的非常透彻,但只能提纲挈领,不能让你玩转某个真正的数据库。感谢c......
  • MySQL - 日志
    1.回滚日志(undolog)作用:保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读内容:逻辑格式的日志(当delete一条记录是,记录一条对应的insert记录,反之亦然),在执行undo的时候,仅仅是将数据从逻辑上恢复至事务之前的状态释放:当事务提交......
  • django使用redis集群、连接池、MySQL连接池
    redis的相关设置CACHES={"default":{"BACKEND":"django_redis.cache.RedisCache","LOCATION":["redis://127.0.0.1:6379/1","redis://127.0.0.1:6380/1",#...],"OPTIONS":{"CLIENT_......
  • mysql 修改密码
    1、找到根目录登录msql   1)以本机为例,mysql安装目录为:usr/localhost/mysql5.7   2)cd  usr/loclahost/mysql5.7/bin    3)登录    4)查看MySQL用户2、 在mysql5.7版本中存放密码字段为authentication_string,再msyql库中#进入mysql库中mysql>......
  • 如何使用mysql.server制作sysytemctl服务
    mysql.server是MySQL的一个启动脚本,通常用于启动、停止、重启和管理MySQL服务。如果你想使用systemctl来管理MySQL服务,你需要创建一个systemd服务文件,因为systemctl是systemd的命令行工具。下面是如何创建和使用systemd服务文件来管理MySQL服务的步骤:首先找......
  • 在Java中连接8.0版本以上的Mysql数据库
    一.连接数据库在使用Java连接8.0版本以上的数据库时,可以按照如下步骤:下载需要的包,本次教程中使用的是下面这个版本。该驱动网上有许多资源,可根据自己的需求下载。建立与数据库的连接单元在合适的包下新建"DButil.java"文件并输入如下代码:importjava.sql.Connecti......
  • 使用 Canal 实时从 MySql 向其它库同步数据
    目前绝大多数项目还是采用mysql作为数据存储,对于用户访问量较高的网站来说,mysql读写性能有限,我们通常会把mysql中的数据实时同步到Redis、mongodb、elasticsearch等中间件中,应对高并发访问场景,减轻mysql压力,防止数据库宕机。在项目开发中,为了不会原有代码进行侵入,采用c......