Top N-query Funktionsweise?

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-query Funktionsweise?
Hallo,

was passiert denn in den einzelnen Schritten dieser Anfrage? Vor allem hinter das Where statement bin ich noch nicht gekommen.

Finden Sie heraus, wer die ältesten zehn Versicherungsnehmer sind.

SELECT COUNT() AS Rang, v1.ID, v1.Geburtsdatum
FROM Versicherungsnehmer v1 , Versicherungsnehmer v2
WHERE v2.Geburtsdatum <= v1.Geburtsdatum
GROUP BY v1.ID, v1.Geburtsdatum
HAVING COUNT(
) <= 10 ORDER BY Rang ASC;

VG,
Speedy


Hi,

bei der TOP-N Abfrage werden Objekte miteinander verglichen. Um Objekte miteinander zu vergleichen willst du meist einen sogenannten self JOIN durchführen. Also z.B. wie folgt:

SELECT *
FROM tablename t1, tablename t2

Auch bei anderen Abfragen (nicht nur TOP N) kann das sehr nützlich sein. Als Ergebnisrelation erhältst du das Kreuzprodukt. Wenn die Tabelle also 100 Tupel hat, erhält deine Ergebnisrelation 100^2 Tupel.

Nun suchst du bei deinem Vergleich Objekte die in irgendetwas besser sind als andere Objekte der gleichen Sorte (schnellere Marathonläufer, Mitarbeiter die mehr verkaufen, Autos mit höheren max Geschwindigkeiten). Hierfür nutzt du z.B. eine WHERE Bedigung:

SELECT t1.Name AS MegaSchnell, t2.Name AS MegaLangsam
FROM tablename t1, tablename t2
WHERE t1.Geschwindigkeit > t2.Geschwindigkeit

Am Ende dieser Abfrage wird die Anzahl an Ergebnissen etwa halbiert. (100^2 - 1)

Bei der TOP N Abfrage speziell ist noch folgende Idee dabei:

  • Was macht den 1. Platz aus? → Es gibt nur 1 anderes Objekt das -mindestens- so gut ist wie es selbst.
  • Was macht den x. Platz aus? → Es gibt x andere Objekte die -mindestens- so gut sind wie es selbst.

In deinem Beispiel ist das Kriterium eben das Alter des Versicherungsnehmers. Wir suchen zu jedem Versicherungsnehmer(vn1) die Anzahl an Versicherungsnehmer(vn2) die noch älter sind als er.

WHERE vn1.Geburtsdatum <= vn2.Geburtsdatum

Das “=” Zeichen kommt wegen der Bedingung -mindestens- so gut. Sonst wäre der 1. Platz gar nicht in der Ergebnisrelation, da ja niemand existiert der älter ist. → WHERE Bedingung wäre immer falsch beim 1. Platz.

Als nächstes kommt das Group By. Wir wollen die Anzahl der Tupel für jeden vn1 Versicherungsnehmer zählen. Daher gruppieren wir nach vn1.Geburtsdatum und vn1.ID. Das hat den Vorteil das wir jetzt mit COUNT(*) zählen können wie viele Leute tatsächlich älter sind.

Nun können wir alle Versicherungsnehmer mit ihrem Rang auf der Rangliste darstellen.
Das HAVING dient dazu nur Platz 1-10 darzustellen und alle anderen Tupel zu entfernen.
Das ORDER BY damit wir eine schön sortierte Rangliste haben und eine willkürliche Reihenfolge.

Hoffe ist etwas klarer geworden.

Notiz am Rande: In der Praxis würde man bei sowas wahrscheinlich oft auch einfach ein LIMIT oder SELECT TOP in Verbindung mit einem Order By machen. Das unterstützen aber nicht alle DBMS und ihr dürft das in KonzMod nicht. Außerdem wäre dann die Abfrage weniger komplex und die Aufgabe nicht so interessant.

Gruß
Christian


Referenz bei IBMIn der Praxis würde ich [m]FETCH FIRST xyz ROWS ONLY[/m] () empfehlen, das ist im Gegensatz zu LIMIT oder SELECT TOP im ANSI SQL Standard verankert worden.
Aber ich gebe dir recht: Es lohnt durchaus, die Funktionsweise des KonzMod-Queries zu verstehen.


Super vielen Dank für die ausführliche Antwort!