You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用单条MySQL查询高效获取多分类多用户的最新25条数据

多分组取最新数据的单查询优化方案

先搞定索引(最关键的一步)

你当前的单字段索引(datetime、category、name)无法高效支撑多条件过滤+排序的需求——MySQL一次只能使用一个索引,查询时要么扫描name索引后再过滤category和datetime,要么扫描datetime索引后再过滤其他字段,效率极低。

必须创建复合索引来匹配你的查询逻辑:

CREATE INDEX idx_name_category_datetime ON `table` (name, category, datetime DESC);

索引顺序不能乱:先按name和category分组,再按datetime降序排列,完美匹配「按分组取最新数据」的需求,数据库能直接定位到目标数据,无需额外排序操作。

两种单查询实现方式

1. UNION ALL 合并查询(兼容所有MySQL版本)

将四个独立查询用UNION ALL合并为单条查询,减少三次连接解析、优化的开销,同时能复用上面的复合索引:

SELECT * FROM `table` WHERE datetime <= 'xxx' AND name = 'john' AND category = 'cat1' ORDER BY datetime DESC LIMIT 25
UNION ALL
SELECT * FROM `table` WHERE datetime <= 'xxx' AND name = 'doe' AND category = 'cat1' ORDER BY datetime DESC LIMIT 25
UNION ALL
SELECT * FROM `table` WHERE datetime <= 'xxx' AND name = 'john' AND category = 'cat2' ORDER BY datetime DESC LIMIT 25
UNION ALL
SELECT * FROM `table` WHERE datetime <= 'xxx' AND name = 'doe' AND category = 'cat2' ORDER BY datetime DESC LIMIT 25;

注意:使用UNION ALL而非UNION——UNION会自动去重,而你这四个分组的数据无重复,没必要额外消耗性能。

2. 窗口函数实现(MySQL 8.0+优先选用)

如果你的MySQL版本为8.0及以上,用ROW_NUMBER()窗口函数能实现更简洁、逻辑更清晰的查询:

SELECT * FROM (
    SELECT 
        *,
        ROW_NUMBER() OVER (PARTITION BY name, category ORDER BY datetime DESC) AS rn
    FROM `table`
    WHERE datetime <= 'xxx'
      AND (name, category) IN (('john', 'cat1'), ('doe', 'cat1'), ('john', 'cat2'), ('doe', 'cat2'))
) AS t
WHERE rn <= 25;

内层查询先过滤出目标分组的数据,再按name+category分组,给每组记录按时间从新到旧编号;外层直接筛选每组编号≤25的记录,即可得到每组最新25条数据。

效果说明

不管选用哪种单查询方式,复合索引都是性能提升的前提——没有该索引,单查询的性能优化效果会很有限。有了索引后,两种方案都比原有的四个独立查询速度快很多:UNION ALL减少了连接开销,窗口函数逻辑更易维护,二者性能表现相近,可根据你的MySQL版本选择。

内容的提问来源于stack exchange,提问作者ipel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 21:35:18