2010-08-03 6 views
8

Ich habe einen Tisch Student (ID, Name, Abteilung, Alter, Score). Ich möchte den jüngsten Schüler finden, der die höchste Punktzahl (unter den jüngsten Schülern) jeder Abteilung hat. In SQL Server kann ich folgende SQL verwenden.Holen Sie sich die oberste Zeile nach der Bestellung von in Oracle Subquery

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). 

jedoch in Oracle, können Sie nicht den Auftrag durch Klausel in Unterabfrage verwenden, und es gibt kein Limit/top wie Keyword. Ich muss die Schüler-Tabelle zweimal mit sich selbst verbinden, um das Ergebnis abzufragen. In Orakel verwende ich folgendes SQL.

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 

Hat jemand eine Idee, das obige SQL für Oracle zu vereinfachen.

+1

In Oracle, Sie * * den Auftrag durch Klausel in einer Unterabfrage verwenden können. –

+0

Es gibt eine Lösung viel einfacher, ohne analytische Funktionen, siehe die akzeptierte Antwort auf meine Frage: http://stackoverflow.com/questions/38180445/oracle-left-join-very-big-table-and-limit-the-joined -rows-to-one-with-the-large – Dany

Antwort

24

versuchen Sie diesen

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

Ich hatte ähnliches Szenario, gedacht, mit pl/sql Block zu behandeln, aber Ihre Lösung hat perfekt funktioniert !! – Rakesh

5

Neben Bharat Antwort ist es möglich, dies mit tun, indem Sie in der Sub-Abfrage in Oracle (als Punkt aus von 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); 

Wenn Sie diese Methode verwenden, sind Sie möglicherweise versucht, die Unterabfrage zu entfernen und einfach rownum = 1 zu verwenden. Dies würde zu einem falschen Ergebnis führen, da die Sortierung nach den Kriterien angewendet würde (Sie würden 1 Zeile erhalten, die sortiert wurde, nicht eine Zeile aus der sortierten Menge).

+0

Die Frage fragt eigentlich die oberste Zeile "jeder Abteilung". Sie verwenden das Departement nicht zum Gruppieren der Ergebnisse. Wahrscheinlich ist diese Antwort nützlich für Leute, die ähnliche Fragen zum Titel stellen, ohne den Inhalt der Frage zu lesen. Aber ich möchte auf den Unterschied hinweisen, dass Leute Lösungen vergleichen (weil sie nicht die gleichen Ergebnisse erzielen). –

+0

@Protron: Guter Fang! Ich habe die Antwort aktualisiert. – 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

Neben Allan Antwort, funktioniert dies auch in Ordnung:

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

Dies gibt nur die oberste Zeile aller Ergebnisse zurück. Das könnte mit dem Fragetitel übereinstimmen. Aber die Frage fragt tatsächlich die oberste Reihe "jeder Abteilung". Deshalb ist es einfacher als Bharat's Antworten. –

+0

Das ist wahr, Protron, ich habe diesen Unterschied eigentlich übersehen und eine einfachere Frage beantwortet, die ich eigentlich selbst gesucht habe, als ich nach diesem Thread gegoogelt habe. Ich nehme an, dass alle Antworten richtig und nützlich sind, je nachdem, wonach der Leser tatsächlich sucht. Zu meinem Zweck war Allans Antwort die nützlichste, und dann habe ich sie verfeinert und neu gepostet. Zu deinem Zweck ist Bharat's Antwort am nützlichsten. Jeder gewinnt! (Obwohl ich bemerkt habe, Allan hat seine Antwort aufgrund Ihrer Aufforderung editiert, aber ich werde meins so lassen, wie es ist, wie es eine perfekte Antwort für viele Leute ist). – SurfingSanta

Verwandte Themen