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

我很难将存储过程从SQL Server转换到Oracle以使我们的产品与其兼容。

我有查询返回一些表的最新logging,基于时间戳:

SQL Server:

SELECT TOP 1 * FROM RACEWAY_INPUT_LABO ORDER BY t_stamp DESC 

=>这将返回我最近的logging

但是甲骨文:

 SELECT * FROM raceway_input_labo WHERE rownum <= 1 ORDER BY t_stamp DESC 

=>这将返回最旧的logging(可能取决于索引),无论ORDER BY语句!

我用这种方式封装了Oracle查询以符合我的要求:

 SELECT * FROM (SELECT * FROM raceway_input_labo ORDER BY t_stamp DESC) WHERE rownum <= 1 

它的工作。 但对我来说这听起来像是一个可怕的黑客攻击,特别是如果我在涉案表中有很多logging的话。

达到这个目标的最好方法是什么?

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 

*将在最后一列返回“1”。 您需要单独列出列以避免这种情况。

改用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 

在上面的评论中logging了一些与此有关的devise问题。 在Oracle中,你需要手动限制结果,当你有大的表和/或具有相同列名的表(并且你不想明确地把它们全部输出并重新命名)。 简单的解决scheme是找出你的断点,并限制在你的查询。 或者你也可以在内部查询中做到这一点,如果你没有冲突的列名限制。 例如

 WHERE m_api_log.created_date BETWEEN TO_DATE ('10/23/2015 05:00', 'MM/DD/YYYY HH24:MI') AND TO_DATE ('10/30/2015 23:59', 'MM/DD/YYYY HH24:MI') 

将大幅削减业绩。 然后你可以ORDER BY,甚至做外部查询来限制行。

另外,我认为TOAD有限制行的function; 但是,不确定在Oracle的实际查询中是否有限制。 不确定。

另一个我build议在这个用例是使用MAX(t_stamp)来获取最新的行…例如

 select t.* from raceway_input_labo t where t.t_stamp = (select max(t_stamp) from raceway_input_labo) limit 1 

我的编码模式首选(可能) – 可靠,通常比尝试从sorting列表中select第一行更好 – 也意图更明确可读。
希望这可以帮助 …

SQLer

只需使用下面的rownum

 select * from (select t.* from raceway_input_labo ril order by t_stamp desc ) where rownum = 1