Oracle SELECT TOP 10 enregistrements
Question
J'ai un gros problème avec une instruction SQL dans Oracle. Je veux choisir le TOP 10 enregistrements commandés par STORAGE_DB qui ne sont pas dans une liste d'une autre instruction select.
Celui-ci fonctionne très bien pour tous les enregistrements:
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')
Mais quand je suis en ajoutant
AND ROWNUM <= 10
ORDER BY STORAGE_GB DESC
Je reçois une sorte de « aléatoires » Records. Je pense que la limite prend en place avant l'ordre.
Est-ce que quelqu'un a une bonne solution? L'autre problème: Cette requête est lente realy (10k + disques)
La solution
comme ci-dessous, vous aurez besoin de mettre votre requête en cours dans la sous-requête:
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 au résultat après qu'il a été retourné. ce que vous devez filtrer le résultat après qu'il a été retourné, donc un sous-requête est nécessaire. Vous pouvez également utiliser RANK () fonction pour obtenir Top-N résultats.
Pour essayer d'utiliser la performance NOT EXISTS
en place de NOT IN
. Voir cette plus.
Autres conseils
Si vous utilisez Oracle 12c, utilisez:
fetch SUIVANT N SEULEMENT RANGS
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
Plus d'infos: http://docs.oracle.com/javadb /10.5.3.0/ref/rrefsqljoffsetfetch.html
En ce qui concerne la mauvaise performance il y a un certain nombre de choses qu'il pourrait être, et il devrait vraiment être une question distincte. Cependant, il y a une chose évidente qui pourrait être un problème:
WHERE TO_CHAR(HISTORY_DATE, 'DD.MM.YYYY') = '06.02.2009')
Si HISTORY_DATE est vraiment une colonne de date et si elle a un indice alors cette réécriture fonctionnera mieux:
WHERE HISTORY_DATE = TO_DATE ('06.02.2009', 'DD.MM.YYYY')
En effet, une conversion du type désactive l'utilisation d'un index B-Tree.
essayer
SELECT * FROM users FETCH NEXT 10 ROWS ONLY;
Vous obtenez un jeu apparemment aléatoire car ROWNUM est appliqué avant la ORDER BY. Ainsi, votre requête prend les dix premières lignes et les tris them.0 Pour sélectionner les dix premiers salaires, vous devez utiliser une fonction analytique dans un sous-requête, puis filtre:
select * from
(select empno,
ename,
sal,
row_number() over(order by sal desc nulls last) rnm
from emp)
where rnm<=10