首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >过滤多个IP的重复数据的统计场景

过滤多个IP的重复数据的统计场景

作者头像
bisal
发布2026-03-12 16:38:21
发布2026-03-12 16:38:21
50
举报

点击标题下「蓝色微信名」可快速关注

最近有个统计数据的需求,数据如下所示,

代码语言:javascript
复制
id	ip	name	insert_time
1	1.1.1.0	a	2025-01-01 00:01:00
2	1.1.1.1	b	2025-01-01 00:01:01
3	1.1.1.0	a	2025-01-01 00:00:01

相同name的ip可能有多条,需要提取最新insert_time的记录,

代码语言:javascript
复制
id	ip	name	insert_time
1	1.1.1.0	a	2025-01-01 00:01:00
2	1.1.1.1	b	2025-01-01 00:01:01

创建测试数据,

代码语言:javascript
复制
CREATE TABLE user_log (
    id INT PRIMARY KEY AUTO_INCREMENT,
    ip VARCHAR(15),
    name VARCHAR(50),
    insert_time DATETIME
);

INSERT INTO user_log (ip, name, insert_time) VALUES
('1.1.1.0', 'a', '2025-01-01 00:01:00'),
('1.1.1.1', 'b', '2025-01-01 00:01:01'),
('1.1.1.0', 'a', '2025-01-01 00:00:01');

select * from user_log;
id|ip     |name|insert_time        |
--|-------|----|-------------------|
 1|1.1.1.0|a   |2025-01-01 00:01:00|
 2|1.1.1.1|b   |2025-01-01 00:01:01|
 3|1.1.1.0|a   |2025-01-01 00:00:01|

MySQL数据库可以有几种方案,

方案1:使用窗口函数(推荐,MySQL 8.0+)

代码语言:javascript
复制
SELECT id, ip, name, insert_time
FROM (
    SELECT *,
           ROW_NUMBER() OVER (PARTITION BY name ORDER BY insert_time DESC) AS rn
    FROM user_log
) t
WHERE rn = 1
ORDER BY id;

方案2:使用JOIN和子查询

代码语言:javascript
复制
SELECT t1.*
FROM user_log t1
INNER JOIN (
    SELECT name, MAX(insert_time) AS max_time
    FROM user_log
    GROUP BY name
) t2 ON t1.name = t2.name AND t1.insert_time = t2.max_time
ORDER BY t1.id;

方案3:使用相关子查询

代码语言:javascript
复制
SELECT *
FROM user_log t1
WHERE insert_time = (
    SELECT MAX(insert_time)
    FROM user_log t2
    WHERE t1.name = t2.name
)
ORDER BY id;

方案4:使用LEFT JOIN自连接

代码语言:javascript
复制
SELECT t1.*
FROM user_log t1
LEFT JOIN user_log t2 
    ON t1.name = t2.name 
    AND t1.insert_time < t2.insert_time
WHERE t2.id IS NULL
ORDER BY t1.id;

以上SQL都可以得到如下的数据,

代码语言:javascript
复制
id|ip     |name|insert_time        |
--|-------|----|-------------------|
 1|1.1.1.0|a   |2025-01-01 00:01:00|
 2|1.1.1.1|b   |2025-01-01 00:01:01|

如果数据量少,可能几个方案都可以采用,但如果数据量多,可能要选择合适的逻辑、创建合适的索引,如果单从效率看,窗口函数相对是最优的,因为它只需要访问一次表,其它的几个方案,都需访问两次,但窗口函数只能用到MySQL 8.0以上的,所以很多低版本的数据库,不能用到这特性,因此还需要根据索引字段的应用,来选择合适方案,没有最优的,只有最合适的。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-12-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 bisal的个人杂货铺 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 方案2:使用JOIN和子查询
  • 方案3:使用相关子查询
  • 方案4:使用LEFT JOIN自连接
  • 以上SQL都可以得到如下的数据,
  • 如果数据量少,可能几个方案都可以采用,但如果数据量多,可能要选择合适的逻辑、创建合适的索引,如果单从效率看,窗口函数相对是最优的,因为它只需要访问一次表,其它的几个方案,都需访问两次,但窗口函数只能用到MySQL 8.0以上的,所以很多低版本的数据库,不能用到这特性,因此还需要根据索引字段的应用,来选择合适方案,没有最优的,只有最合适的。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档