Oracle数据库排序后取第一条及分组取首行的SQL实现
在Oracle数据库开发中,经常需要获取按特定条件排序后的第一条记录,或者对数据进行分组后提取每组的最新/最优项。本文将分别介绍使用传统ROWNUM机制和现代窗口函数ROW_NUMBER()的两种标准写法,确保查询结果的准确性与性能。
场景:单表排序后获取唯一的第一条数据
在处理业务数据时,常见需求是:指定某个主键或ID,按照时间或其他字段倒序排列,并取出排在第一位的那条记录。例如,我们需要从儿童健康检查表中,找出某人在符合条件且未取消的情况下,最近一次随访的日期。
第1步:基础查询逻辑分析
假设我们有一个需求:获取指定人员(person_info_id)在近期随访(is_Cancel = 0)中的最新一条跟进日期。NEXT_FOLLOWUP_DATE是我们想要提取的目标字段。
虽然可以直接通过ORDER BY进行排序,但在Oracle中不能直接在外层使用WHERE ROWNUM = 1配合ORDER BY来保证获取的是"排序后"的第一条,因为ROWNUM是在结果集生成过程中分配的,而非排序后。
第2步:使用嵌套子查询实现Top-1
为了确保先完成排序,再截取第一条,需要采用两层查询结构:
内部子查询:负责根据条件过滤(where person_info_id = '...' and is_cancel = 0)并按要求排序(order by followup_visit_date desc)。
外部查询:基于内部已排序的结果,利用rownum = 1限制仅返回第一行。
SELECT NEXT_FOLLOWUP_DATE
FROM (
SELECT NEXT_FOLLOWUP_DATE
FROM PH_CHILD_HEALTH_EXAM
WHERE person_info_id = '3afc119ab460497d85f59b1e135ea6b1'
AND is_cancel = 0
ORDER BY followup_visit_date DESC
)
WHERE rownum = 1;
这种写法是Oracle早期的经典模式,适用于只需获取全局排序后第一行的场景。
进阶:分组后获取每组数据的第一条
当数据量较大且需要按某一维度(如部门、类别、个人)进行分组,并希望保留每组中根据另一指标(如创建时间、优先级)排序后的第一条记录时,传统GROUP BY往往难以满足需求(因为它会丢失其他非聚合字段)。此时,推荐使用Oracle强大的窗口函数。
第3步:利用ROW_NUMBER()窗口函数
窗口函数ROW_NUMBER()可以为每一组数据生成唯一的行号。配合PARTITION BY(分组)和ORDER BY(组内排序),可以轻松实现"每组取一"的逻辑。
-- 伪代码示例:Test1表
SELECT *
FROM (
SELECT ROW_NUMBER() OVER (
PARTITION BY x -- 按照字段x分组
ORDER BY y DESC -- 在组内按照字段y降序排列
) rn, -- 生成分组内的序号rn
test1.* -- 选中需要的其他字段
FROM test1 -- 原数据表
) temp_table -- 给子查询起别名
WHERE rn = 1; -- 仅保留每个分组中标号为1的行
核心参数说明
PARTITION BY x:定义分组的依据,类似于GROUP BY的效果,但不会合并行。ORDER BY y DESC:定义组内数据的排序规则。此处以倒序为例,表示取每组中y值最大的一条。rn = 1:外层过滤条件,筛选出每个分区的第一名。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持本站!以上就是Oracle数据库排序后获取第一条及分组获取首行的详细内容,更多关于Oracle SQL技巧的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









