oracle rank() over 求最后一条记录

本文介绍了在资产管理的供需平衡监控业务中,如何利用Oracle的RANK() OVER函数来获取每个充电站的最新分析结果。通过PARTITION BY和ORDER BY子句进行分组和时间倒序排序,取RANK为1的记录即可。同时,文章还对比了RANK()、DENSE_RANK()和ROW_NUMBER()的区别。
业务场景:
资产管理中的供需平衡监控。现在又如下“供需分析统计结果”表

[img]http://dl.iteye.com/upload/attachment/593716/0e48bc8e-8c58-3660-926c-52a9399001fd.jpg[/img]
现在需要求每个充电站的最新分析结果。

WITH SUPPLY_TEMP AS
(SELECT A.STAT_ID,
RANK() OVER(PARTITION BY A.SUBS_ID, A.EQUIP_CATEG, A.EQUIP_CODE_ID ORDER BY A.STAT_DATE DESC) RANK1,
B.ORG_NO,
B.ORG_NAME,
C.SUBS_NAME,
A.EQUIP_CATEG,
A.EQUIP_CODE_ID,
A.STOCK_NUM,
A.PLAN_DIST_NUM,
A.DISTING_NUM,
A.MAX_SS,
A.MIN_SS,
A.EST_USE_NUM,
A.EST_SUPPLY_END_DATE
FROM D_SUPPLYDMD_STAT A, O_ORG B, C_SUBS C
WHERE A.ORG_NO = B.ORG_NO
AND A.SUBS_ID = C.SUBS_ID
AND A.STAT_DATE > ADD_MONTHS(SYSDATE, -1)
ORDER BY A.ORG_NO)
SELECT * FROM SUPPLY_TEMP B WHERE B.RANK1 = 1

可以通过 RANK() OVER(PARTITION BY A.SUBS_ID, A.EQUIP_CATEG, A.EQUIP_CODE_ID ORDER BY A.STAT_DATE DESC)来分组、排序来获取序列,
求最新的分析结果 只要按照分析时间(STAT_DATE)倒序排序,再取rank为1的结果就是不同充电站的最后一条分析记录了。
最后把网上关于 rank () over , row_number() over ,rank_dense ()之间的区别列一下。
1,2,2,4,5,6.。。。。这是rank()的形式

1,2,2,3,4,5,。。。。这是dense_rank()的形式

1,2,3,4,5,6.。。。。。这是row_number()涵数形式
<think>我们正在使用Oracle数据库,需要查询某字段最大值对应的整条记录。在Oracle中,有几种方法可以实现这个需。 常见的方法包括: 1. 使用子查询:先获取最大值,然后根据这个最大值查询对应的记录。 2. 使用ROW_NUMBER()窗口函数:为每条记录按目标字段降序排列,然后取排名第一的记录。 3. 使用FIRST_VALUE()函数:获取分组中的第一个值(结合排序)。 4. 使用KEEP (DENSE_RANK FIRST ...)语法:Oracle特有的语法,可以直接获取最大值对应的记录。 考虑到用户的需是“某字段取值最大的一条数据”,我们假设表名为`table_name`,字段名为`max_field`,并且可能存在多条记录具有相同的最大值,但用户只需要其中一条(或者需要全部,问题中说的是“一条”,但实际需可能不同,这里我们先按一条处理,同时也可以提供获取多条的方法)。 方法1:使用子查询(适用于最大值只有一条记录的情况,如果有多条,则会返回多条) ```sql SELECT * FROM table_name WHERE max_field = (SELECT MAX(max_field) FROM table_name); ``` 方法2:使用ROW_NUMBER()(可以确保只返回一条,即使有多个最大值也只取一条) ```sql SELECT * FROM ( SELECT t.*, ROW_NUMBER() OVER (ORDER BY max_field DESC) AS rn FROM table_name t ) WHERE rn = 1; ``` 方法3:使用KEEP语法(Oracle特有,可以获取最大值对应的任意一条记录,这里取第一条) ```sql SELECT * FROM ( SELECT t.*, MAX(max_field) OVER () AS max_value FROM table_name t ) WHERE max_field = max_value AND ROWNUM = 1; -- 这里使用ROWNUM=1来只取一条 ``` 但是,如果用户想要获取最大值对应的所有记录(即如果最大值有多个,则全部返回),那么方法1就可以,而方法2需要稍作修改(使用RANK()或DENSE_RANK())来获取所有最大值记录。 方法4:使用KEEP语法获取最大值对应的整条记录(可以返回多条,但每条记录都是最大值对应的记录) 注意:KEEP语法通常用于聚合,如果我们想同时获取整条记录,可以这样写: ```sql SELECT MAX(max_field) AS max_value, MAX(column1) KEEP (DENSE_RANK FIRST ORDER BY max_field DESC) AS column1, MAX(column2) KEEP (DENSE_RANK FIRST ORDER BY max_field DESC) AS column2, ... -- 需要列出所有字段,并且每个字段都使用MAX(或MIN等)聚合函数和KEEP子句 FROM table_name; ``` 这种方法比较繁琐,需要列出所有字段,并且每个字段都要用聚合函数包裹,因此不常用。 更简洁的方法是使用FIRST_VALUE()窗口函数,但同样需要为每个字段写一次: ```sql SELECT DISTINCT FIRST_VALUE(column1) OVER (ORDER BY max_field DESC) AS column1, FIRST_VALUE(column2) OVER (ORDER BY max_field DESC) AS column2, ... FROM table_name; ``` 但这样会返回多行(因为DISTINCT可能无法合并),所以也不常用。 因此,我们推荐使用前两种方法,根据具体需选择。 总结: - 如果最大值对应的记录只有一条,或者需要所有最大值对应的记录,使用方法1。 - 如果只需要最大值对应的任意一条记录(例如在最大值有多个时只取一条),可以使用方法2(ROW_NUMBER)并取rn=1,或者使用方法1加上ROWNUM=1(但注意,这样可能随机取一条,因为子查询返回多条时顺序不定,所以最好在子查询中排序)。 但是,注意:在Oracle中,如果最大值有多个,方法1会返回多条记录。如果用户只需要一条,可以加上ROWNUM限制。 例如,只取一条: ```sql SELECT * FROM ( SELECT * FROM table_name WHERE max_field = (SELECT MAX(max_field) FROM table_name) ORDER BY some_column -- 可选,按某个字段排序后取第一条 ) WHERE ROWNUM = 1; ``` 根据用户的需,这里我们给出两种主要情况的解决方案: 情况1:获取最大值对应的所有记录 使用简单的子查询即可。 情况2:只获取最大值对应的一条记录(任意一条或按某种顺序的第一条) 使用子查询并限制ROWNUM=1,或者使用ROW_NUMBER()。 根据引用[1]中提到的,在MySQL中group by可能会取非分组字段的第一条,但在Oracle中,我们这里不使用group by,而是使用上述方法。 另外,引用[4]提到Oracle的异常处理,但这个问题与异常处理无关,所以忽略。 因此,我们给出以下示例: 假设表名为`employees`,字段`salary`,我们想获取工资最高的员工记录(所有记录): ```sql SELECT * FROM employees WHERE salary = (SELECT MAX(salary) FROM employees); ``` 如果只想获取一条(如果有多个最高工资,只取一条): ```sql SELECT * FROM ( SELECT * FROM employees WHERE salary = (SELECT MAX(salary) FROM employees) ORDER BY employee_id -- 可以按某个字段排序,确保取到的是期望的那一条,比如按id最小的 ) WHERE ROWNUM = 1; ``` 或者使用ROW_NUMBER(): ```sql SELECT * FROM ( SELECT e.*, ROW_NUMBER() OVER (ORDER BY salary DESC) AS rn FROM employees e ) WHERE rn = 1; ``` 注意:ROW_NUMBER()方法在没有排序字段的情况下,如果多个记录都是最大值,那么它们都会按照相同的salary排序,但ROW_NUMBER()会赋予不同的行号(1,2,3...),所以只取rn=1的那一条。而如果不指定其他排序条件,那么这多条记录的顺序是不确定的。因此,为了确保确定性,通常会在ORDER BY中加入第二个字段(如主键): ```sql SELECT * FROM ( SELECT e.*, ROW_NUMBER() OVER (ORDER BY salary DESC, employee_id) AS rn FROM employees e ) WHERE rn = 1; ``` 这样,在工资相同的情况下,会按employee_id排序,然后取第一个。 综上所述,根据用户的具体需选择合适的方法。 相关问题: 1. 如何查询Oracle中某字段最小值对应的整条记录? 2. 在Oracle中如何获取每个分组的最大值对应的记录? 3. 如何优化Oracle中查询最大值对应记录的SQL性能?</think>### Oracle 查询某字段最大值对应的整条记录Oracle 中获取某字段最大值对应的完整记录,有以下几种高效方法: #### 方法 1:子查询 + 等值匹配(推荐) ```sql SELECT * FROM your_table WHERE your_column = (SELECT MAX(your_column) FROM your_table); ``` **说明**: - 先通过子查询获取最大值,再通过等值匹配获取完整记录 - 执行效率高,适合大多数场景 - 如果最大值有重复,会返回多条记录 #### 方法 2:ROW_NUMBER() 窗口函数 ```sql SELECT * FROM ( SELECT t.*, ROW_NUMBER() OVER (ORDER BY your_column DESC) AS rn FROM your_table t ) WHERE rn = 1; ``` **说明**: - 使用窗口函数按目标字段降序排序 - `rn=1` 获取最大值对应的第一条记录 - 如需处理重复值,可改用 `RANK()` 函数 #### 方法 3:KEEP...FIRST 语法(Oracle 特有) ```sql SELECT * FROM your_table WHERE your_column = ( SELECT MAX(your_column) FROM your_table ) AND ROWNUM = 1; -- 仅取第一条记录 ``` **说明**: - 结合子查询和 `ROWNUM` 限制结果数量 - 适合只需要单条记录的场景 - 性能优于窗口函数[^2] #### 方法 4:FIRST_VALUE 窗口函数 ```sql SELECT DISTINCT FIRST_VALUE(column1) OVER (ORDER BY your_column DESC) AS col1, FIRST_VALUE(column2) OVER (ORDER BY your_column DESC) AS col2, ... FROM your_table; ``` **说明**: - 为每个字段单独获取最大值对应的值 - 适合只需要特定列的场景 --- ### 性能对比 | 方法 | 执行效率 | 适用场景 | 重复值处理 | |------------|----------|------------------------|------------------| | 子查询匹配 | ★★★★ | 通用场景 | 返回所有重复记录 | | ROW_NUMBER | ★★★☆ | 需要排序号 | 可控制返回条数 | | KEEP语法 | ★★★★★ | Oracle专属高效方案 | 需手动控制 | | FIRST_VALUE| ★★☆☆ | 仅需部分字段 | 返回单条记录 | > **最佳实践**: > 1. 单条记录 → 使用方法3(`KEEP...FIRST + ROWNUM`) > 2. 完整记录 → 使用方法1(子查询匹配) > 3. 大数据量表 → 确保目标字段有索引[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值