sql server窗口函数要求rows between必须显式包含current row锚点,不支持postgresql的range时间间隔语法,且order by重复值时结果不可复现,需加唯一辅助排序字段。

SQL Server里ROWS BETWEEN必须带CURRENT ROW锚点
SQL Server对帧子句语法更严格,ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING这种写法会直接报错。它要求窗口边界必须以CURRENT ROW为显式锚点,合法写法只能是ROWS BETWEEN 1 PRECEDING AND CURRENT ROW或ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING。
如果你真需要“前一行 + 当前行 + 后一行”这种对称窗口,得改用ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING——但SQL Server不认,只能退而求其次:先用LAG()和LEAD()把前后值拉出来,再手工AVG()计算,或者用子查询模拟。
- 错误示例:
ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING→ 报错Incorrect syntax near 'FOLLOWING' - 正确写法(向前2期):
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW - 想包含后行?只能用
LEAD(amount, 1)+LEAD(amount, 2)+ 当前行,再(amount + lead1 + lead2) / 3
PostgreSQL支持RANGE BETWEEN时间间隔,SQL Server不原生支持
PostgreSQL可以直接写RANGE BETWEEN INTERVAL '7 days' PRECEDING AND CURRENT ROW,按真实时间跨度滑动;SQL Server没这个语法,RANGE只支持数值型排序字段(比如id),不能解析INTERVAL或日期运算。
在SQL Server里实现“过去7天销售额均值”,你得手动构造边界条件:要么用WHERE sale_date >= DATEADD(day, -6, CURRENT_DATE)加子查询,要么用JOIN自关联+日期差过滤,逻辑臃肿且难优化。
PostgreSQL 18.4 官方 Ubuntu 安装包现已发布,这是目前最新的稳定版本。推荐通过官方 APT 仓库安装:先执行 sudo apt update 更新索引,再运行 sudo apt install postgresql-18 即可完成部署。新版本引入了异步 I/O 子系统,在顺序扫描与 VACUUM 场景下性能提升显著,同时支持 UUID v7 原生生成函数与虚拟生成列。
- PostgreSQL一行搞定:
AVG(amount) OVER (ORDER BY sale_date RANGE BETWEEN INTERVAL '6 days' PRECEDING AND CURRENT ROW) - SQL Server必须绕路:窗口函数无法直接表达时间范围,
RANGE对DATE类型基本失效 - 后果:SQL Server中时间类滑动平均更倾向用
ROWS+ 预处理补全每日记录(避免空天断层)
PARTITION BY行为一致,但ORDER BY重复值处理风险不同
两者都要求PARTITION BY显式声明分组字段,漏掉就会跨组混算——这点完全一致。但当ORDER BY字段存在重复值(比如批量插入的create_time完全相同),PostgreSQL默认按物理存储顺序补序,SQL Server则可能因执行计划变化导致行序浮动,结果不可复现。
这不是bug,是标准允许的行为差异。要稳定结果,必须加唯一辅助排序字段:
- 推荐写法:
ORDER BY create_time, id或ORDER BY create_time, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY id) - 别依赖
ORDER BY create_time单独排序,尤其在金融、日志类场景 - SQL Server中若用
GETDATE()作为排序字段,高并发下毫秒级重复极常见,风险更高
NULL值和边界收缩逻辑相同,但类型返回值有隐式差异
两者对NULL的处理一致:默认忽略,AVG()只算非空值;第一行窗口不足时也自动收缩,不报错。但返回类型不同:AVG()在SQL Server中默认返回FLOAT,PostgreSQL返回NUMERIC,精度和舍入方式可能不一致。
如果业务要求精确到小数点后两位,又跨数据库部署,不能依赖默认行为:
- 显式转类型:
CAST(AVG(amount) AS DECIMAL(10,2)) - 避免直接比对浮点结果,尤其做ETL校验时
- PostgreSQL中
NUMERIC精度高,但聚合大数据量时内存开销略大
WHERE或HAVING子句里,而PostgreSQL虽然也不行,但有人误以为FILTER能替代——其实FILTER只用于聚合函数,不适用于窗口函数。想过滤移动平均结果,必须套一层子查询或CTE。










