You need to enable JavaScript to run this app. Oracle FIRST/LAST中KEEP子句的定义及有无该子句的效果解析
优惠活动
大模型
产品
解决方案
定价
更多

Oracle FIRST/LAST中KEEP子句的定义及有无该子句的效果解析

Oracle FIRST/LAST聚合语法中KEEP子句详解

KEEP子句的准确定义

  • KEEP不属于独立的语法关键字,是Oracle FIRST/LAST聚合函数的原生内置组成部分。很多人检索时找不到单独的官方说明条目,本质是因为官方文档没有将其拆分独立说明,所有规则都归在SQL语言参考的FIRST、LAST函数章节下。
  • 它的标准执行逻辑分为两步:
    1. 按照子句内ORDER BY指定的列,对分组内的全部数据做密集排名(DENSE_RANK),仅保留排名处于第一(FIRST)位置或最后(LAST)位置的行,过滤掉其余无关行
    2. 对第一步筛选出的目标子集,执行外层指定的聚合计算(如MAX、MIN、SUM、COUNT等)
  • 它的核心价值,就是解决聚合计算的取值列、和用来定位目标行的排序列不一致的场景问题——这也是普通聚合语法天生覆盖不了的能力边界。

使用与不使用KEEP子句的效果差异

不使用KEEP子句的效果

常规分组聚合(如直接使用MAX、MIN)的执行逻辑是:对分组内每一个待计算的列,独立计算该列的极值,完全不校验不同列的极值取值是否来自同一行。
以典型的地址档案查询场景为例:需要为每个关联人取截止指定日期,最新生效(startdate最大)的那条地址记录的全部字段。如果不使用KEEP,常见写法是:

SELECT
    ra.relation_id,
    MAX(ra.startdate) AS startdate,
    MAX(ra.address) AS address,
    MAX(ra.postal_code) AS postal_code,
    MAX(ra.city) AS city
FROM relation_addresses ra
WHERE ra.startdate <= TO_DATE(:reference_date, 'yyyy-mm-dd')
GROUP BY ra.relation_id

这种写法的天然缺陷是:MAX(ra.startdate) 拿到的最新生效日期,和另外三个字段列各自取的字典序最大值,极有可能不属于同一行——比如最新地址的城市名不是所有历史记录里字典序最大的,最后返回的结果会把不同行的字段拼接起来,完全不是目标的最新地址真实信息。

使用KEEP子句的效果

加上KEEP子句后,整个聚合的执行顺序会被调整为:

  1. 先按照GROUP BY维度完成分组
  2. 针对每个分组,按照KEEP子句内ORDER BY指定的排序列(如startdate)完成密集排名,先筛选出排名处于目标位置(如LAST代表取最大排序列值的所有行)的子集
  3. 再对这个目标子集内的字段,执行外层的聚合计算,保证所有字段的取值都来自排序列定位的目标行集合
    对应优化后的写法:
SELECT
    ra.relation_id,
    MAX(ra.startdate) AS startdate,
    MAX(ra.address) KEEP (DENSE_RANK LAST ORDER BY ra.startdate) AS address,
    MAX(ra.postal_code) KEEP (DENSE_RANK LAST ORDER BY ra.startdate) AS postal_code,
    MAX(ra.city) KEEP (DENSE_RANK LAST ORDER BY ra.startdate) AS city
FROM relation_addresses ra
WHERE ra.startdate <= TO_DATE(:reference_date, 'yyyy-mm-dd')
GROUP BY ra.relation_id

这种写法返回的地址、邮编、城市字段,全部来自startdate最大的目标行,不会出现多列极值行错位的问题,完全匹配业务查询需求。

补充说明:如果分组内存在多条排序列取值相同的行(比如同一个关联人在同一天录入了两条地址记录),KEEP子句会把所有同排名的行都保留下来,外层的MAX/MIN聚合会在这个同排名行集合内计算最终的取值结果。

内容的提问来源于stack exchange,提问作者mon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.07 15:27:03