Как правильно использовать Oracle ORDER BY и ROWNUM?



мне трудно конвертировать хранимые процедуры из SQL Server в Oracle, чтобы наш продукт был совместим с ним.



у меня есть запросы, которые возвращают самую последнюю запись некоторых таблиц, на основе метки времени:



SQL Server:



SELECT TOP 1 *
FROM RACEWAY_INPUT_LABO
ORDER BY t_stamp DESC


=> это вернет мне самую последнюю запись



но Oracle:



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


=> это вернет мне самую старую запись (возможно, в зависимости от индекс), независимо от ORDER BY заявление!



Я инкапсулировал запрос Oracle таким образом, чтобы соответствовать моим требованиям:



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


и это работает. Но это звучит как ужасный хак для меня, особенно если у меня много записей в соответствующих таблицах.



каков наилучший способ достичь этого ?

1488   5  

5 ответов:

The where заявление выполняется до the 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

альтернативой, которую я бы предложил в этом случае использования, является использование MAX(t_stamp) для получения последней строки ... например,

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

мой предпочтительный шаблон кодирования (возможно) - надежный, обычно выполняет или лучше, чем попытка выбрать 1 - ю строку из отсортированного списка-также намерение более явно читается.
Надеюсь, это поможет ...

SQLer

документированы несколько проблем с дизайном с этим в комментарии выше. Короче говоря, в Oracle вам нужно ограничить результаты вручную, когда у вас есть большие таблицы и/или таблицы с одинаковыми именами столбцов (и вы не хотите явно вводить их все и переименовывать их все). Простое решение-определить точку останова и ограничить ее в запросе. Или вы также можете сделать это во внутреннем запросе, если у вас нет ограничения конфликтующих имен столбцов. Е. Г.

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')  

будут резать вниз результаты существенно. Затем вы можете заказать или даже сделать внешний запрос для ограничения строк.

кроме того, я думаю, что жаба имеет функцию ограничения строк; но, не уверен, что это ограничение в пределах фактического запроса на Oracle. Не уверенный.

просто используйте rownum, как показано ниже

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

Comments

    Ничего не найдено.