SQL如何高效提取每组首条记录 ROW_NUMBER优化策略

ROW_NUMBER()必须配合PARTITION BY和ORDER BY才能实现分组取首条,单独使用仅生成全局序号;正确写法需在子查询中指定分组与排序,并将WHERE条件下推至内层以提升性能。ROW_NUMBER() 必须配合 PARTITION BY 和 ORDER BY 才能分组取首条单独写 ROW_NUMBER() 不会自动按某列分组,不加 PARTITION BY 就变成全表编号,根本不是"每组首条"。常见错误是只写 ORDER BY,结果得到的是全局序号,一查就发现所有记录的 rn 都是 1 到 N 连续值,完全没分组。正确做法是明确指定分组字段和排序逻辑:SELECT * FROM ( SELECT *, ROW_NUMBER() OVER ( PARTITION BY user_id ORDER BY created_at DESC ) AS rn FROM orders) t WHERE rn = 1;PARTITION BY user_id 表示"每个 user_id 算一组"ORDER BY created_at DESC 决定哪条是"首条"------这里取最新订单;若要最早,改用 ASC外层 WHERE rn = 1 是必须的,窗口函数不能直接在 WHERE 中过滤ORDER BY 字段缺失索引会导致全表扫描数据库执行 ROW_NUMBER() 时,如果 ORDER BY 的字段没索引,尤其是大表上,性能会断崖式下跌。不是慢一点,是可能从毫秒级跳到几秒甚至超时。比如按 created_at 排序却没建索引,MySQL 或 PostgreSQL 都得临时排序整个分区数据,内存不够还会落盘,IO 成瓶颈。检查执行计划:看是否出现 Using filesort(MySQL)或 Sort 节点(PostgreSQL)复合索引更有效:对 PARTITION BY a ORDER BY b,优先建 (a, b) 联合索引注意 NULL 处理:如果 ORDER BY 字段允许 NULL,且业务要求 NULL 排最后,显式写 ORDER BY col DESC NULLS LAST(PostgreSQL 支持,MySQL 8.0+ 可用 IS NULL 模拟)替代方案:用 DISTINCT ON(PostgreSQL)或 FIRST_VALUE(通用但有陷阱)DISTINCT ON 在 PostgreSQL 里是更轻量的写法,语义清晰、通常更快,但它只存在于 PostgreSQL,跨数据库不可移植。 RedClaw 百度推出的手机端万能AI Agent助手

相关推荐
金銀銅鐵1 小时前
[Python] 模 n 乘法的逆元计算器
python·数学·游戏
aqi001 小时前
15天学会AI应用开发(十)把文本嵌入模型换成国产模型
人工智能·python·ai编程
吃糖的小孩3 小时前
给 QQ AI 机器人设计“可控记忆”:会话摘要、手动长期记忆与角色卡边界
数据库
金銀銅鐵18 小时前
[Python] 扩展欧几里得算法
python·数学·算法
Duckdblab18 小时前
DuckDB 性能调优终极指南:打造闪电般的分析体验
python
带派擂总19 小时前
Python全栈开发精华版最全合集(包含各种面试题) Day24_异常和错误
python
笃行35021 小时前
金仓数据库数据安全双防线:静态存储加密与传输加密实战
数据库
笃行35021 小时前
金仓数据库物理备份实战:sys_rman 全流程演练与误覆盖抢救
数据库
笃行35021 小时前
金仓数据库逻辑备份实战:从全库导出到 Schema 替换的完整闭环
数据库