Oracle 实现分组取前N条记录

本文通过使用ROWNUM伪例及分析函数介绍如何在Oracle中实现分组并选取每组的前N名记录,提供了两种不同的实现方法。
开发工具与关键技术:Oracle sql * plus PLSQL Developer
作者:唐国铭
撰写时间:2019年03月28日

在实际中我们会遇到把数据进行分组然后取前N条的情况,比如要获取各科成绩前三名的记录,以下是我个人利用ROWNUM 伪例写出来的,代码有点长,基本思路利用子查询嵌套和连表查询得出

  1. 先把各科成绩分组后按SCORE成绩倒序排序,然后嵌套子查询后期ROWNUNM值后把此查询命名为SC表,
    在这里插入图片描述
  2. 再把各科成绩排序中最大的那个ROWNUM值获取命名为SC2表
    在这里插入图片描述
    即得出分组排序后各科成绩最大的值所对应的ROWNUM
  3. 最后利用JOIN ON把两表连接起来,添加筛选条件
    在这里插入图片描述
    过后查看资料得出了更加简短的SQL语句
    在这里是利用分析函数得出每个组的ROWNUM值,因为这是直接得出每个组的排序值,所以直接筛选即可:
    在这里插入图片描述
<think>我们正在讨论Oracle中如何对查询结果排序后10记录。根据引用[2]和引用[3]提供的方法,我们可以使用ROWNUM伪列或者FETCHFIRST子句(Oracle12c及以上版本)来实现。 ###方法1:使用ROWNUM(适用于所有Oracle版本)ROWNUM是Oracle在查询结果返回分配的伪列,表示返回行的顺序号(从1开始)。注意:ROWNUM是在数据被检索出来之后才分配的,因此我们需要在子查询中先排序,然后再使用ROWNUM过滤。 ```sqlSELECT *FROM (SELECT*FROM your_tableORDERBY your_sort_column DESC--按你的排序字段和排序方式(ASC/DESC) )WHERE ROWNUM<=10;``` ###方法2:使用FETCH FIRST子句(Oracle12c及以上版本) Oracle12c引入了FETCHFIRST子句,可以更简洁地实现这个需求。 ```sqlSELECT *FROM your_tableORDER BYyour_sort_column DESCFETCH FIRST10ROWSONLY;--只10行``` ###补充说明-如果排序字段有重复值,并且希望包含所有与第10记录相同值的记录,可以使用`WITH TIES`(仅适用于FETCH FIRST子句):```sqlSELECT*FROM your_tableORDERBY your_sort_columnDESCFETCH FIRST10ROWSWITH TIES;--会返回所有与第10记录相同值的记录``` -使用ROWNUM方法时,如果排序字段有重复值,并且希望包含相同值的记录,则需要更复杂的处理(比如使用窗口函数),但通常使用FETCH FIRSTWITH TIES更简单。 ###示例假设有一个员工表`employees`,我们想按工资降序排序10记录:```sql--方法1SELECT *FROM (SELECT*FROMemployeesORDERBY salaryDESC) WHEREROWNUM <=10; --方法2(12c及以上) SELECT* FROMemployeesORDER BYsalary DESCFETCH FIRST10ROWSONLY;``` ###注意事项1. **性能考虑**:当表很大时,先排序再N行可能会消耗较多资源。确保排序字段有索引可以提高性能。 2. **版本兼容性**:如果数据库版本低于12c,则只能使用ROWNUM方法。 ###相关问题1.如何实现Oracle查询结果的分页(例如第11到20记录)?2.Oracle中如何对分组后的每组数据N记录?3.FETCHFIRST子句和ROWNUM在性能上有何差异? 以上方法都可以根据实际需求调整排序字段和排序方式(升序/降序)。[^2]: Oracle数据库技巧:轻松查询N记录[^3]:Oracle只获10数据</think>在 Oracle 数据库中,对查询结果排序后 10 记录有以下几种常用方法,根据您的 Oracle 版本和需求选择最合适的方案: ### 方法 1:使用 ROWNUM 伪列(兼容所有版本) ```sql SELECT * FROM ( SELECT * FROM your_table ORDER BY sort_column DESC -- 替换为您的排序列和排序方式 ) WHERE ROWNUM <= 10; ``` **特点**: - 最通用的方法,适用于所有 Oracle 版本 - 子查询中先排序,外层用 `ROWNUM` 限制行数 - 性能较好,尤其对大数据集[^2] ### 方法 2:使用 FETCH FIRST(Oracle 12c 及以上) ```sql SELECT * FROM your_table ORDER BY sort_column DESC FETCH FIRST 10 ROWS ONLY; ``` **特点**: - 语法简洁直观(SQL:2008 标准) - 性能与 `ROWNUM` 相当 - 支持高级选项: ```sql -- 包含并列的第10名 FETCH FIRST 10 ROWS WITH TIES; -- 10%的记录 FETCH FIRST 10 PERCENT ROWS ONLY; ``` ### 方法 3:使用窗口函数(复杂场景) ```sql SELECT * FROM ( SELECT t.*, ROW_NUMBER() OVER (ORDER BY sort_column DESC) AS rn FROM your_table t ) WHERE rn <= 10; ``` **适用场景**: - 需要分组每组 N 时(配合 `PARTITION BY`) - 需要同时获排名信息时 - 处理并列排名更灵活 ### 性能对比与建议 | **方法** | **版本要求** | **性能** | **功能扩展性** | |----------------|-------------|---------|---------------| | ROWNUM | 所有版本 | ★★★★ | ★★☆ | | FETCH FIRST | 12c+ | ★★★★☆ | ★★★★ | | 窗口函数 | 8i+ | ★★★☆ | ★★★★★ | **实际应用示例**: ```sql -- 获销售额最高的10个产品 SELECT product_id, product_name, total_sales FROM ( SELECT product_id, product_name, SUM(sales) AS total_sales FROM sales_data GROUP BY product_id, product_name ORDER BY SUM(sales) DESC ) WHERE ROWNUM <= 10; ``` ### 注意事项 1. **索引优化**:确保排序列有索引,否则全表排序代价高 2. **并列处理**:`WITH TIES` 可能返回多于10行 3. **分页查询**:获第11-20记录需使用: ```sql SELECT * FROM ( SELECT t.*, ROW_NUMBER() OVER (ORDER BY id) rn FROM your_table t ) WHERE rn BETWEEN 11 AND 20; ``` 根据 Oracle 官方文档,在 12c 及以上版本推荐使用 `FETCH FIRST` 语法,它更符合 SQL 标准且可读性更好[^3]。对于旧版本,`ROWNUM` 仍是可靠选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值