Erhalten Sie Top-Ergebnisse für jede Gruppe (in Oracle)
-
02-07-2019 - |
Frage
Wie würde ich in der Lage sein, N-Ergebnisse für mehrere Gruppen zu erhalten in Orakel-Abfrage.
Zum Beispiel, angesichts der folgenden Tabelle:
|--------+------------+------------|
| emp_id | name | occupation |
|--------+------------+------------|
| 1 | John Smith | Accountant |
| 2 | Jane Doe | Engineer |
| 3 | Jack Black | Funnyman |
|--------+------------+------------|
Es gibt viele weitere Reihen mit mehr Berufen. Ich hätte gern drei Mitarbeiter (sagen wir mal) von jedem Beruf.
Gibt es eine Möglichkeit, dies zu tun, ohne eine Unterabfrage?
Lösung
Dies erzeugt, was Sie wollen, und es verwendet keine herstellerspezifischen SQL-Funktionen wie TOP N oder RANK ().
SELECT MAX(e.name) AS name, MAX(e.occupation) AS occupation
FROM emp e
LEFT OUTER JOIN emp e2
ON (e.occupation = e2.occupation AND e.emp_id <= e2.emp_id)
GROUP BY e.emp_id
HAVING COUNT(*) <= 3
ORDER BY occupation;
In diesem Beispiel gibt es die drei Mitarbeiter mit den niedrigsten emp_id-Werten pro Besatzung. Sie können das in der Ungleichung Vergleich verwendete Attribut ändern, um es die besten Mitarbeiter mit Namen zu machen geben, oder was auch immer.
Andere Tipps
Ich habe keine Oracle-Instanz praktisch im Augenblick so habe ich nicht getestet:
select *
from (select emp_id, name, occupation,
rank() over ( partition by occupation order by emp_id) rank
from employee)
where rank <= 3
Hier ist ein Link, wie Rang funktioniert: http://www.psoug.org/reference /rank.html
Add rownum Rang:
select * from
(select emp_id, name, occupation,rank() over ( partition by occupation order by emp_id,RowNum) rank
from employee)
where rank <= 3
diese in SQL Server getestet (und es verwendet subquery)
select emp_id, name, occupation
from employees t1
where emp_id IN (select top 3 emp_id from employees t2 where t2.occupation = t1.occupation)
nur tun, eine ORDER von in der Unterabfrage an Ihren Bedürfnissen anpassen
Ich bin mir nicht sicher, dass dies sehr effizient ist, aber vielleicht ein Startplatz?
select *
from people p1
join people p2
on p1.occupation = p2.occupation
join people p3
on p1.occupation = p3.occupation
and p2.occupation = p3.occupation
where p1.emp_id != p2.emp_id
and p1.emp_id != p3.emp_id
Das sollten Sie Reihen geben, die 3 verschiedene Mitarbeiter alle in der gleichen Besetzung enthalten. Leider wird es alle denkbaren Kombinationen von denen geben.
Kann das jemand abspecken bitte?