over developer 11g sql oracle sql-order-by rownum

sql - developer - ¿Cómo usar Oracle ORDER BY y ROWNUM correctamente?



rownum oracle (5)

Me está resultando difícil convertir los procedimientos almacenados de SQL Server a Oracle para que nuestro producto sea compatible.

Tengo consultas que devuelve el registro más reciente de algunas tablas, en función de una marca de tiempo:

Servidor SQL:

SELECT TOP 1 * FROM RACEWAY_INPUT_LABO ORDER BY t_stamp DESC

=> Eso me devolverá el registro más reciente

Pero Oracle:

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

=> Eso me devolverá el registro más antiguo (probablemente dependiendo del índice), ¡independientemente de la instrucción ORDER BY !

Encapsulé la consulta de Oracle de esta manera para que coincida con mis requisitos:

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

y funciona. Pero me parece un hack horrible, especialmente si tengo muchos registros en las tablas involucradas.

Cuál es la mejor manera de lograr esto ?


Documentado un par de problemas de diseño con esto en un comentario anterior. En el cuento corto, en Oracle, debe limitar los resultados manualmente cuando tenga tablas y / o tablas grandes con los mismos nombres de columna (y no quiere explicitarlas explícitamente y cambiarles el nombre a todas). La solución fácil es descubrir su punto de corte y limitarlo en su consulta. O también puede hacer esto en la consulta interna si no tiene la restricción de nombres de columna conflictiva. P.ej

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

reducirá los resultados sustancialmente. Luego puede ORDENAR o incluso hacer la consulta externa para limitar las filas.

Además, creo que TOAD tiene una función para limitar las filas; pero no estoy seguro de que eso limite la consulta real en Oracle. No es seguro.


La instrucción where se ejecuta antes del order by . Por lo tanto, su consulta deseada es decir " tomar la primera fila y luego ordenarla por t_stamp desc ". Y eso no es lo que intentas.

El método de subconsulta es el método adecuado para hacer esto en Oracle.

Si desea una versión que funcione en ambos servidores, puede usar:

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

El exterior * devolverá "1" en la última columna. Debería enumerar las columnas individualmente para evitar esto.


Solo use Rownum como el siguiente

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


Una alternativa que sugeriría en este caso de uso es usar MAX (t_stamp) para obtener la última fila ... por ej.

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

Mi preferencia de patrón de codificación (tal vez) - confiable, generalmente funciona igual o mejor que tratar de seleccionar la 1ª fila de una lista ordenada - también la intención es más explícitamente legible.
Espero que esto ayude ...

SQLer


Use ROW_NUMBER() lugar. ROWNUM es una pseudocolumna y ROW_NUMBER() es una función. Puede leer sobre la diferencia entre ellos y ver la diferencia en el resultado de las siguientes consultas:

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