Oracle SELECT TOP 10 registros
Pregunta
Tengo un gran problema con una sentencia de SQL en Oracle. Quiero seleccionar entre los 10 primeros registros clasificadas por STORAGE_DB que no están en una lista de una otra instrucción de selección.
Éste bien funciona para todos los registros:
SELECT DISTINCT
APP_ID,
NAME,
STORAGE_GB,
HISTORY_CREATED,
TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE
FROM HISTORY WHERE
STORAGE_GB IS NOT NULL AND
APP_ID NOT IN (SELECT APP_ID
FROM HISTORY
WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009')
Pero cuando estoy añadiendo
AND ROWNUM <= 10
ORDER BY STORAGE_GB DESC
Me estoy poniendo algún tipo de registros "al azar". Creo que es porque el límite toma en su lugar antes de la orden.
¿Alguien tiene una buena solución? El otro problema: Esta consulta es realmente lenta (10K + registros)
Solución
Usted tendrá que poner su consulta actual en la subconsulta de la siguiente manera:
SELECT * FROM (
SELECT DISTINCT
APP_ID,
NAME,
STORAGE_GB,
HISTORY_CREATED,
TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE
FROM HISTORY WHERE
STORAGE_GB IS NOT NULL AND
APP_ID NOT IN (SELECT APP_ID FROM HISTORY WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') ='06.02.2009')
ORDER BY STORAGE_GB DESC )
WHERE ROWNUM <= 10
rownum al resultado después de que haya sido devuelto. lo que necesita para filtrar el resultado después de que haya sido devuelto, por lo que se requiere una subconsulta. También puede utilizar RANK () la función para obtener Top-N resultados.
Para obtener un rendimiento trate de usar NOT EXISTS
en lugar de NOT IN
. Ver este por más.
Otros consejos
Si está utilizando Oracle 12c, utilice:
FETCH SIGUIENTE N sólo las filas
SELECT DISTINCT
APP_ID,
NAME,
STORAGE_GB,
HISTORY_CREATED,
TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') AS HISTORY_DATE
FROM HISTORY WHERE
STORAGE_GB IS NOT NULL AND
APP_ID NOT IN (SELECT APP_ID FROM HISTORY WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') ='06.02.2009')
ORDER BY STORAGE_GB DESC
FETCH NEXT 10 ROWS ONLY
Más información: http://docs.oracle.com/javadb /10.5.3.0/ref/rrefsqljoffsetfetch.html
En cuanto a los malos resultados hay cualquier cantidad de cosas que podría ser, y lo que realmente debería ser una cuestión aparte. Sin embargo, hay una cosa obvia que podría ser un problema:
WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009')
Si HISTORY_DATE realmente es una columna de fecha y si tiene un índice entonces esta reescritura se obtienen mejores resultados:
WHERE HISTORY_DATE = TO_DATE ('06.02.2009', 'DD.MM.YYYY')
Esto se debe a una conversión de tipo de datos deshabilita el uso de un índice B-Tree.
try
SELECT * FROM users FETCH NEXT 10 ROWS ONLY;
Se obtiene un conjunto aparentemente aleatoria porque ROWNUM se aplica antes de que el ORDER BY. Por lo que su consulta toma las primeras filas y diez tipos them.0 para seleccionar los diez mejores salarios que debe utilizar una función analítica en una subconsulta, entonces filtro que:
select * from
(select empno,
ename,
sal,
row_number() over(order by sal desc nulls last) rnm
from emp)
where rnm<=10