2010-08-03 3 views
8

J'ai un étudiant de table (identifiant, nom, département, âge, score). Je veux trouver le plus jeune étudiant qui a le score le plus élevé (parmi les élèves les plus jeunes) de chaque département. Dans SQL Server, je peux utiliser SQL suivant.Obtenir la ligne supérieure après la commande dans Oracle Sous-requête

select * from student s1 
where s1.id in 
(select s2.id from student s2 
where s2.department = s1.department order by age asc, score desc top 1). 

Cependant, dans Oracle, vous ne pouvez pas utiliser la commande par clause et sous-requête il n'y a pas de limite/mot-clé comme supérieure. Je dois rejoindre la table des étudiants avec deux fois pour interroger le résultat. Dans Oracle, j'utilise SQL suivant.

select s1.* from student s1, 
(select s2.department, s2.age, max(s2.score) as max_score from student s2, 
(select s3.department, min(s3.age) as min_age from student s3 group by s3.department) tmp1 where 
s2.department = tmp1.department and s2.age = tmp1.min_age group by s2.department, s2.age) tmp2 
where s1.department =tmp2.department and s1.age = tmp2.age and s1.score=tmp2.max_score 

Est-ce que quelqu'un a une idée pour simplifier le SQL ci-dessus pour oracle.

+1

Dans Oracle, vous * pouvez * utiliser la commande par clause dans une sous-requête. –

+0

Il existe une solution beaucoup plus simple, sans fonctions analytiques, voir la réponse acceptée à ma question: http://stackoverflow.com/questions/38180445/oracle-left-join-very-big-table-and-limit-the-joined -rows-to-one-with-the-large – Dany

Répondre

24

essayez celui-ci

select * from 
    (SELECT id, name, department, age, score, 
    ROW_NUMBER() OVER (partition by department order by age desc, score asc) srlno 
    FROM student) 
where srlno = 1; 
+0

J'ai eu un scénario similaire, pensé pour gérer l'utilisation du bloc pl/sql, mais votre solution a parfaitement fonctionné !! – Rakesh

5

En plus de la réponse de Bharat, il est possible de le faire en utilisant ORDER BY dans la sous-requête dans Oracle (comme le point par Jeffrey Kemp):

SELECT * 
FROM student s1 
WHERE s1.id IN (SELECT id 
       FROM (SELECT id, ROWNUM AS rn 
         FROM  student s2 
         WHERE s1.department = s2.department 
         ORDER BY age ASC, score DESC) 
       WHERE rn = 1); 

Si vous utilisez cette méthode, vous pouvez être tenté de supprimer la sous-requête et d'utiliser simplement rownum = 1. Cela entraînerait un résultat incorrect car le tri serait appliqué après les critères (vous obtiendriez une ligne triée, et non une rangée de l'ensemble trié).

+0

La question demande réellement la rangée supérieure de "chaque département". Vous n'utilisez pas le département pour regrouper les résultats. Probablement cette réponse est utile pour les personnes qui cherchent des questions similaires au titre sans lire le contenu de la question. Mais je tiens à souligner la différence pour les personnes comparant les solutions (car elles n'obtiendront pas les mêmes résultats). –

+0

@Protron: Bonne prise! J'ai mis à jour la réponse. – Allan

1
select to_char(job_trigger_time,'mm-dd-yyyy') ,job_status from 
(select * from kdyer.job_instances ji INNER JOIN kdyer.job_param_values pm 
on((ji.job_id = pm.job_id) and (ji.job_spec_id = '10003') and (pm.param_value='21692')) 
order by ji.job_trigger_time desc) 
where rownum<'2' 
10

En plus de la réponse d'Allan, cela fonctionne très bien aussi:

select * 
from (SELECT * 
    FROM student 
    order by age asc, 
      score desc) 
where rownum = 1; 
+0

Cela renvoie uniquement la première ligne de tous les résultats. Cela pourrait correspondre au titre de la question. Mais la question demande en fait la rangée supérieure de "chaque département". C'est pourquoi c'est plus simple que les réponses de Bharat. –

+0

C'est vrai Protron, j'ai manqué cette distinction, et j'ai répondu à une question plus simple, qui était en fait ce que je cherchais moi-même quand j'ai cherché sur google et trouvé ce fil. Donc, je suppose que toutes les réponses sont correctes et utiles, en fonction de ce que le lecteur recherche réellement. Pour ma part, la réponse d'Allan était la plus utile, puis je l'ai affinée et republiée. Pour votre but, la réponse de Bharat est la plus utile. Tout le monde gagne! (Bien que j'ai noté qu'Allan a édité sa réponse à cause de vos suggestions, mais je vais laisser la mienne telle quelle, car c'est une réponse parfaite pour beaucoup de gens). – SurfingSanta

Questions connexes