web-dev-qa-db-fra.com

Oracle SELECT TOP 10 enregistrements

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)

117
opHASnoNAME

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.

173
Padmarag

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

26
Volpato

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.

22
APC

essayer

SELECT * FROM users FETCH NEXT 10 ROWS ONLY;
13
Shaaban

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
10
vijaya