J'ai un gros problème avec une instruction SQL dans Oracle. Je souhaite sélectionner le TOP 10 des enregistrements commandés par STORAGE_DB qui ne figurent pas dans une liste provenant d'une autre instruction select.
Celui-ci fonctionne 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 j'ajoute
AND ROWNUM <= 10
ORDER BY STORAGE_GB DESC
Je reçois une sorte de "aléatoire" Records. Je pense parce que la limite prend effet avant la commande.
Est-ce que quelqu'un a une bonne solution? L'autre problème: cette requête est vraiment lente (10k + enregistrements)
Vous devrez mettre votre requête actuelle dans la sous-requête comme ci-dessous:
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
Oracle applique rownum au résultat une fois renvoyé.
Vous devez filtrer le résultat une fois renvoyé. Une sous-requête est donc requise. Vous pouvez également utiliser la fonction RANK () pour obtenir les meilleurs résultats.
Pour améliorer les performances, utilisez NOT EXISTS
à la place de NOT IN
. Voir this pour plus.
Si vous utilisez Oracle 12c, utilisez:
FETCH NEXT N ROWS UNIQUEMENT
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 les performances médiocres, il pourrait y avoir un certain nombre de choses, et cela devrait vraiment être une question distincte. Cependant, il y a une chose évidente qui pourrait poser 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 index, cette réécriture fonctionnera mieux:
WHERE HISTORY_DATE = TO_DATE ('06.02.2009', 'DD.MM.YYYY')
En effet, une conversion de type de données désactive l'utilisation d'un index B-Tree.
essayer
SELECT * FROM users FETCH NEXT 10 ROWS ONLY;
Vous obtenez un ensemble apparemment aléatoire car ROWNUM est appliqué avant ORDER BY. Donc, votre requête prend les dix premières lignes et les trie. Pour sélectionner les dix salaires les plus élevés, vous devez utiliser une fonction analytique dans une sous-requête, puis filtrer les éléments suivants:
select * from
(select empno,
ename,
sal,
row_number() over(order by sal desc nulls last) rnm
from emp)
where rnm<=10