如何高效实现带总条数统计的SQL分页查询?
单次操作实现分页查询+总数统计的优化方案
针对你需要一次完成条件过滤、分页数据获取、总条数统计的需求,不同主流数据库都有原生的简洁方案,无需拆分两次查询或使用临时表,以下是具体实现:
MySQL 8.0+ / MariaDB 10.2+
利用CTE(公共表表达式)结合窗口函数COUNT() OVER(),一次过滤数据集即可同时拿到分页数据和总条数:
WITH filtered_data AS ( SELECT *, COUNT(*) OVER() AS total_count FROM your_table WHERE your_filter_condition -- 替换为你的业务过滤条件 ) SELECT * FROM filtered_data LIMIT 25 OFFSET 49; -- 对应"显示第50-75条"(OFFSET从0开始计数)
执行时数据库会仅扫描一次符合条件的数据集,同时计算总条数并返回分页结果,避免资源浪费。
SQL Server 2012+
借助OFFSET ... FETCH语法配合窗口函数,一次查询完成所有操作:
SELECT *, COUNT(*) OVER() AS total_count FROM your_table WHERE your_filter_condition ORDER BY sort_column -- SQL Server要求OFFSET必须搭配ORDER BY OFFSET 49 ROWS FETCH NEXT 25 ROWS ONLY;
优化器会自动合并过滤、统计、分页的逻辑,仅执行一次核心数据扫描。
PostgreSQL
直接在主查询中嵌入窗口函数,配合LIMIT/OFFSET实现需求:
SELECT *, COUNT(*) OVER() AS total_count FROM your_table WHERE your_filter_condition ORDER BY sort_column LIMIT 25 OFFSET 49;
PostgreSQL的查询优化器会自动识别逻辑,避免重复扫描数据集,性能优于两次独立查询。
关键注意事项
- 务必为过滤条件涉及的字段创建合适的索引,这是保证大数据集下性能的基础。
- 若处理千万级以上超大数据集,可通过
EXPLAIN查看执行计划,确认是否仅执行了一次过滤扫描。 - 窗口函数
COUNT(*) OVER()会在过滤后的数据集上计算总条数,无需额外扫描全表,资源占用远低于临时表方案。
内容的提问来源于stack exchange,提问作者Sidney
相关产品推荐
相关产品推荐

