SQL中LAST_VALUE()窗口函数使用RANGE边界未按预期返回结果的问题咨询
SQL中LAST_VALUE()窗口函数使用RANGE边界未按预期返回结果的问题咨询
嘿,我来帮你搞明白这个问题!先把你的场景和核心疑问理清楚:
你运行了这段SQL查询:
select e.first_name , e.last_name, ed.department_name , e.salary, last_value(concat(e.first_name, ' ', e.last_name)) over(partition by ed.department_name order by salary range between unbounded preceding and unbounded following) UnboundedCol, last_value(concat(first_name, ' ', last_name)) over(partition by ed.department_name order by salary range between 0 preceding and 0 following) range0, last_value(concat(first_name, ' ', last_name)) over(partition by ed.department_name order by salary range between 1 preceding and 1 following) range1, last_value(concat(first_name, ' ', last_name)) over(partition by ed.department_name order by salary range between 2 preceding and 2 following) range2, last_value(concat(first_name, ' ', last_name)) over(partition by ed.department_name order by salary range between 3 preceding and 3 following) range3 from employees e join employee_departments ed on e.department_id = ed.department_id order by ed.department_name, salary;
你发现在Finance部门里,比如Jose Manuel Urman那一行,range1列的结果还是他自己,但你预期应该是下一行的John Chen——你以为range between 1 preceding and 1 following是取前后各1行,但实际结果和range0完全一致,这到底是怎么回事?
核心原因:你混淆了RANGE和ROWS的窗口边界逻辑!
RANGE不是按行数来计算窗口的,而是按排序列的数值范围!
拿你的例子拆解:
- Jose Manuel的salary是7800
range between 1 preceding and 1 following的真实含义是:salary值在7800-1到7800+1之间的所有行,也就是7799 ≤ salary ≤7801- 看Finance部门的salary列表:上一行是7700,下一行是8200——这两个数值都不在7799-7801的区间里,所以这个窗口里只有Jose Manuel自己一行
- 那
LAST_VALUE()自然就只能返回他自己了
而你说用ROWS模式正常,是因为ROWS才是按行的位置偏移计算窗口:rows between 1 preceding and 1 following就是取当前行的前1行、当前行、后1行,这时候窗口里包含了John Chen,LAST_VALUE()就会返回窗口里最后一行的他。
再举个例子帮你加深理解
假设Finance部门里有另一个员工,salary是7801,那Jose Manuel的range1窗口就会包含这个员工——这时候LAST_VALUE()就会返回这个salary7801的员工(因为按salary排序,他在Jose Manuel后面)。
关键知识点总结
RANGE:基于排序列的数值范围划分窗口,N preceding/following是指当前行排序列值±N的区间ROWS:基于行的位置偏移划分窗口,N preceding/following是指前后N行
这就是为啥你用RANGE的时候,range0到range3结果都一样——因为你的salary值之间的差距远大于1、2、3,所以这些范围里都只有当前行自己。
备注:内容来源于stack exchange,提问作者DumbCoder
相关产品推荐
相关产品推荐

