如何在TSQL中高效筛选百万级数据里每组值的最新记录?
嗨,这个问题我太熟悉了!处理百万级数据里每个手机号的最新记录筛选,核心得兼顾效率和准确性,下面给你几种不同数据库环境下的实战方案,都是经过验证的高效写法:
核心思路:分组取最新
针对每个MobileNumber,我们要么先找到它对应的最大Date值,再关联回原表拿完整记录;要么用窗口函数直接标记出每个分组内的最新行再过滤。后者在现代数据库里性能更优,尤其是配上合适的索引,百万级数据也能快速出结果。
方案1:窗口函数(首推,大数据量友好)
用ROW_NUMBER()窗口函数可以给每个手机号分组内的记录按Date降序编号,编号为1的就是最新那一行。这种方法只需要扫描一次表(有索引的话更快),性能拉满。
适配MySQL 8.0+/PostgreSQL/SQL Server 的写法
SELECT CampaignName, MobileNumber, Date FROM ( SELECT CampaignName, MobileNumber, Date, -- 按手机号分组,日期倒序排,给每条记录编序号 ROW_NUMBER() OVER (PARTITION BY MobileNumber ORDER BY Date DESC) AS rn FROM your_table_name ) AS sub_query WHERE rn = 1; -- 只取序号为1的最新记录
必加优化:给MobileNumber和Date建联合索引,让数据库不用全表扫描就能快速分组排序:
CREATE INDEX idx_mobile_date ON your_table_name(MobileNumber, Date DESC);
这个索引能把查询时间从分钟级直接压到秒级甚至毫秒级,对百万级数据来说至关重要。
方案2:关联子查询(兼容低版本数据库)
如果你的数据库不支持窗口函数(比如MySQL 5.x),可以用子查询先找出每个手机号的最大日期,再关联原表获取对应记录:
SELECT t1.CampaignName, t1.MobileNumber, t1.Date FROM your_table_name t1 INNER JOIN ( -- 先分组拿到每个手机号的最新日期 SELECT MobileNumber, MAX(Date) AS latest_date FROM your_table_name GROUP BY MobileNumber ) t2 ON t1.MobileNumber = t2.MobileNumber AND t1.Date = t2.latest_date;
小提示:如果同一个手机号在同一时间有多条记录(Date完全相同),这个方案会返回所有这些记录;要是只需要其中一条,可以结合LIMIT或者额外加排序条件,或者优先用方案1的窗口函数(可以再加个排序字段比如CampaignName,确保唯一)。
方案3:MySQL 专属优化写法(适合字段少的场景)
要是用的是MySQL,还可以用GROUP_CONCAT配合SUBSTRING_INDEX来实现,不过这种方法更适合字段不多的情况:
SELECT -- 按日期倒序拼接CampaignName,取第一个就是最新的 SUBSTRING_INDEX(GROUP_CONCAT(CampaignName ORDER BY Date DESC), ',', 1) AS CampaignName, MobileNumber, MAX(Date) AS Date FROM your_table_name GROUP BY MobileNumber;
注意:如果CampaignName里包含逗号,记得换个分隔符,比如:
SUBSTRING_INDEX(GROUP_CONCAT(CampaignName ORDER BY Date DESC SEPARATOR '|'), '|', 1)
关键性能提醒
- 一定要建
(MobileNumber, Date DESC)的联合索引,这是百万级数据高效查询的核心。 - 别用
SELECT *,只查需要的字段,减少数据传输和内存占用。 - 如果表数据持续增长,定期清理旧数据或者按日期做分区表,能进一步提升查询速度。
内容的提问来源于stack exchange,提问作者MaliceUK
相关产品推荐
相关产品推荐

