如何正确使用Oracle ORDER BY和ROWNUM?

Lar*_*rry 110 sql oracle sql-order-by rownum

我很难将存储过程从SQL Server转换为Oracle,以使我们的产品与之兼容.

我有查询根据时间戳返回一些表的最新记录:

SQL Server:

SELECT TOP 1 *
FROM RACEWAY_INPUT_LABO
ORDER BY t_stamp DESC
Run Code Online (Sandbox Code Playgroud)

=>这将使我回到最近的记录

甲骨文:

SELECT *
FROM raceway_input_labo 
WHERE  rownum <= 1
ORDER BY t_stamp DESC
Run Code Online (Sandbox Code Playgroud)

=>那将返回最旧的记录(可能取决于索引),无论ORDER BY声明如何!

我以这种方式封装了Oracle查询以满足我的要求:

SELECT * 
FROM 
    (SELECT *
     FROM raceway_input_labo 
     ORDER BY t_stamp DESC)
WHERE  rownum <= 1
Run Code Online (Sandbox Code Playgroud)

它的工作原理.但这听起来像是一个可怕的黑客,特别是如果我在相关的表格中有很多记录.

实现这一目标的最佳方法是什么?

Gor*_*off 109

where声明被执行之前order by.所以,你想要的查询是" 取第一行,然后通过 t_stamp desc 命令 ".这不是你想要的.

子查询方法是在Oracle中执行此操作的正确方法.

如果您想要一个适用于两个服务器的版本,您可以使用:

select ril.*
from (select ril.*, row_number() over (order by t_stamp desc) as seqnum
      from raceway_input_labo ril
     ) ril
where seqnum = 1
Run Code Online (Sandbox Code Playgroud)

外部*将在最后一列中返回"1".您需要单独列出列以避免这种情况.


Art*_*Art 32

ROW_NUMBER()改用.ROWNUM是一个伪列,ROW_NUMBER()是一个函数.您可以阅读它们之间的差异,并查看以下查询的输出差异:

SELECT * FROM (SELECT rownum, deptno, ename
           FROM scott.emp
        ORDER BY deptno
       )
 WHERE rownum <= 3
 /

ROWNUM    DEPTNO    ENAME
---------------------------
 7        10    CLARK
 14       10    MILLER
 9        10    KING


 SELECT * FROM 
 (
  SELECT deptno, ename
       , ROW_NUMBER() OVER (ORDER BY deptno) rno
  FROM scott.emp
 ORDER BY deptno
 )
WHERE rno <= 3
/

DEPTNO    ENAME    RNO
-------------------------
10    CLARK        1
10    MILLER       2
10    KING         3
Run Code Online (Sandbox Code Playgroud)

  • `ROWNUM`可能比`ROW_NUMBER()`更快,所以无论是否应该使用一个而不是另一个因素取决于许多因素. (2认同)

use*_*860 13

从 Oracle 12c 开始,我们现在有了行限制子句来执行此操作。

SELECT *
FROM raceway_input_labo 
ORDER BY t_stamp DESC
FETCH FIRST ROW ONLY
Run Code Online (Sandbox Code Playgroud)

或者针对不同场景的许多替代方案(前 n 行、平局处理等)。