如何将含KEEP子句的Oracle SQL转换为PostgreSQL等效语句
Oracle 特殊窗口语法转 PostgreSQL 等效实现
原语句逻辑说明
待转换的Oracle SQL使用了KEEP(DENSE_RANK LAST)专属语法,核心逻辑为:按NUMBER字段分区,每个分区内以UPD_DATE升序排列(NULL值排在最前),取排序后排名最末位的分组中最大的USER_ID值,作为同分区所有行的返回结果。
原SQL代码如下:
SELECT MAX(TKI1.USER_ID) KEEP(DENSE_RANK LAST ORDER BY TKI1.UPD_DATE NULLS FIRST) OVER(PARTITION BY TKI1.NUMBER) AS USER_ID FROM USER_TABLE TKI1;
PostgreSQL 可直接执行的等效语句
PostgreSQL没有原生的KEEP子句支持,通过标准窗口函数+FILTER过滤即可实现完全一致的逻辑,写法如下:
SELECT MAX(TKI1.USER_ID) FILTER (WHERE rk = 1) OVER (PARTITION BY TKI1."NUMBER") AS USER_ID FROM ( SELECT *, DENSE_RANK() OVER ( PARTITION BY "NUMBER" ORDER BY UPD_DATE DESC NULLS LAST ) AS rk FROM USER_TABLE TKI1 ) TKI1;
逻辑对应说明
- 原语句
DENSE_RANK LAST ORDER BY UPD_DATE NULLS FIRST的本质是取分区内UPD_DATE值最大的记录分组:升序排列时NULL排在最前,意味着NULL为最小的UPD_DATE值,排序最末尾的就是UPD_DATE最大的分组。PostgreSQL中通过ORDER BY UPD_DATE DESC NULLS LAST倒序排列,排名rk=1的记录刚好对应原逻辑中最末位的DENSE_RANK分组。 - 外层
MAX(USER_ID) FILTER (WHERE rk = 1)配合分区窗口,等效于原KEEP子句中取目标分组内最大USER_ID的逻辑。 - 注意
NUMBER是PostgreSQL保留关键字,如果字段名确实为NUMBER,必须用双引号包裹,否则会触发语法错误。
内容的提问来源于stack exchange,提问作者tantn10
相关产品推荐
相关产品推荐

