SQLite 3.25.0+ 才支持窗口函数,旧版本执行 ROW_NUMBER() OVER 会报“near 'OVER': syntax error”;必须带 PARTITION BY 和 ORDER BY,且 ORDER BY 需加 rowid 等唯一字段保证稳定性;WHERE 不能直接引用窗口别名,须用子查询或 CTE 套用。

SQLite 3.25+ 才支持窗口函数,旧版直接报错
SQLite 在 3.25.0(2018年发布)才首次引入窗口函数;低于这个版本(比如常见的 3.19、3.8.11)执行 ROW_NUMBER() OVER 会直接报错:near "OVER": syntax error。不是语法写错,是引擎根本不认识 OVER 关键字。
检查版本方法:SELECT sqlite_version(); —— 若结果 < 3.25.0,必须升级或换方案。
- 升级到
3.30.0+更稳妥:对CASE在ORDER BY中的支持更完整,避免某些自定义排序场景下报misuse of aggregate: COUNT() - 若无法升级,用子查询模拟(兼容所有 SQLite 版本),但性能随数据量下降明显
- 别信“加 extension 就能启用”——窗口函数是核心语法层特性,非插件可补
ROW_NUMBER() 必须带 PARTITION BY 和 ORDER BY,缺一不可
在 SQLite 中写 ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) 是合法的;但漏掉 PARTITION BY 就变成全表编号,漏掉 ORDER BY 则报错:ORDER BY clause required in window function。
常见错误写法:
-
ROW_NUMBER() OVER (PARTITION BY dept)→ 缺ORDER BY,语法错误 -
ROW_NUMBER() OVER (ORDER BY salary DESC)→ 没PARTITION BY,结果不是“每部门前三”,而是全表按薪资排号 -
SELECT *, ROW_NUMBER() OVER (...) AS rn FROM t GROUP BY dept→GROUP BY和窗口函数混用,报错:no such column: rn或聚合字段缺失提示
正确结构只能是子查询或 CTE:
SELECT dept, name, salary
FROM (
SELECT dept, name, salary,
ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC, id) AS rn
FROM employees
)
WHERE rn <= 3;
ORDER BY 里必须加稳定二级排序,否则结果不可复现
SQLite 的 ROW_NUMBER() 在排序值相同时,编号顺序取决于行物理存储位置或扫描顺序——不保证一致。比如两个员工同薪,第一次查 A 是第 1 名、B 是第 2 名;下次可能反过来。
解决方法:在 ORDER BY 末尾加一个唯一字段兜底,推荐主键或 rowid:
- ✅ 推荐:
ORDER BY salary DESC, rowid(rowid在 SQLite 中天然唯一且轻量) - ✅ 可用:
ORDER BY salary DESC, id(如果表有自增id字段) - ❌ 避免:
ORDER BY salary DESC, name(同名情况多,仍不稳定) - ❌ 避免:
ORDER BY salary DESC, random()(每次结果都变,无法用于分页或审计)
注意:rowid 不是所有表都有——只存在于未显式定义 INTEGER PRIMARY KEY 的普通表;若已定义主键为 INTEGER 类型,则该列就是 rowid 的别名,可直接用。
WHERE 不能直接引用窗口别名,必须套子查询
这是 SQLite(和其他 SQL 引擎)的执行顺序决定的:WHERE 在窗口函数计算前就执行,所以 WHERE rn <= 3 会报错:no such column: rn。
唯一合规写法是两层嵌套:
- 内层:计算
rn并暴露给外层 - 外层:用
WHERE过滤rn字段 - 不能用
HAVING替代——HAVING只作用于聚合,而rn不是聚合结果
CTE 写法等价但更清晰:
WITH ranked AS (
SELECT dept, name, salary,
ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC, rowid) AS rn
FROM employees
)
SELECT dept, name, salary
FROM ranked
WHERE rn <= 3;
别省略子查询/CTE——这是硬性限制,不是风格选择。

















