Top N

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

Top N
Servus,

hat jemand vielleicht in der Fragestunde mitgeschrieben wie man genau das Top N Problem in einer möglichst einfachen Art löst?
Wäre für ne schöne Erklärung dankbar.


Zum Beispiel so:

select count(*), p1.Name
from Personen p1, Personen p2
where p1.Gehalt >= p2.Gehalt
group by p2.PNr, p2.Name
having count(*) <= 10

Im ersten Schritt baust du dir so eine Tabelle:

1  1
2  1
2  2
3  1
3  2
3  3
4  1
4  2
4  3
4  4

Durch das Gruppieren nach p2:

1  1
2  1
3  1
4  1
----
2  2
3  2
4  2
----
3  3
4  3
----
4  4

Und die [m]count[/m]s der einzelnen Gruppen sind dann der Rang (vorausgesetzt, es gibt keine zwei gleichen Einträge…)

Es gäbe auch noch eine andere Methode mit einem Haufen [m]select[/m]s, aber…


Sicher das das Query so stimmt? Hätte gesagt man sucht solche p2 raus die weniger als 10 p1 über ihnen haben die mehr verdienen, aber du projezierst im SELECT auf p1.Name statt auf p2.Name.


Ups… :blush:

Aber so müsst’s passen:

select count(*), p2.Name
from Personen p1, Personen p2
where p1.Gehalt >= p2.Gehalt
group by p2.PNr, p2.Name
having count(*) <= 10

Ich störe mich noch daran, dass “die TOP(10) der Spitzenverdiener für jede Abteilung ermittelt werden sollen, aber das ist wohl eher ein Fehler in der Aufgabenformulierung. Ich schätze mal, dass es schon so gemeint war, wie der immoartl es gemacht hat.


„Innerhalb einer Abteilung“? Sprich: alle Leute ausgeben die innerhalb mindestens einer Abteilung TOP(10) Verdiener sind, in der sie auch arbeiten? Dann wohl einfach nur solche vergleichen die in der gleichen Abteilung sind und die Vergleichs-Gruppen auch auf Abteilungsebene bilden und vllt nur die max. Rankings von jeder Person anzeigen.
Also, dann wohl so irgendwie:
select PNr, max(„Rang innerhalb einer Abteilung“) as "max. Rang innerhalb einer Abteilung
FROM
(select p2.PNr, p2.Name, count() as „Rang innerhalb einer Abteilung“
from Personen p1, Personen p2
where p1.Gehalt >= p2.Gehalt AND p1.Abteilung = p2.Abteilung
group by p2.PNr, p2.Name, p2.Abteilung
having count(
) <= 10)
group by PNr, Name


Vielleicht so was in der Art:

select a.ANr, count(*), a.Nachname, a.Vorname
    from Personen a, Personen b
    where a.ANr = b.ANr and a.Gehalt <= b.Gehalt
    group by a.ANr, a.PNr
    order by a.ANr, count(*)
    having count(*) <= 10