Diese Frage geht auf eine Diskussion darüber zurück, ob die SQL-Ranking-Funktionalität in einer Datenbank verwendet werden soll oder nicht. besonderer Fall .
Jedes gängige RDBMS enthält einige Ranking-Funktionen, d. h. seine Abfragesprache enthält Elemente wie TOP n ... ORDER BY key
, ROW_NUMBER() OVER (ORDER BY key)
ou ORDER BY key LIMIT n
( Übersicht ).
Sie eignen sich hervorragend zur Steigerung der Leistung, wenn Sie nur einen kleinen Teil einer großen Anzahl von Datensätzen präsentieren möchten. Aber sie bergen auch einen großen Fallstrick: Wenn key
nicht eindeutig ist, sind die Ergebnisse nicht-deterministisch. Betrachten Sie das folgende Beispiel:
users
user_id name
1 John
2 Paul
3 George
4 Ringo
logins
login_id user_id login_date
1 4 2009-08-17
2 1 2009-08-18
3 2 2009-08-19
4 3 2009-08-20
Eine Abfrage soll die Person zurückgeben, die sich zuletzt angemeldet hat:
SELECT TOP 1 users.*
FROM
logins JOIN
users ON logins.user_id = users.user_id
ORDER BY logins.login_date DESC
Genau wie erwartet George
zurückgegeben wird und alles gut aussieht. Aber dann wird ein neuer Datensatz eingefügt in logins
Tisch:
1 4 2009-08-17
2 1 2009-08-18
3 2 2009-08-19
4 3 2009-08-20
5 4 2009-08-20
Was ergibt die obige Abfrage jetzt? Ringo
? George
? Das kann man nicht sagen. Soweit ich mich erinnere, gibt z.B. MySQL 4.1 den ersten physisch erstellten Datensatz zurück, der den Kriterien entspricht, d.h. das Ergebnis wäre George
. Dies kann jedoch von Version zu Version und von DBMS zu DBMS variieren. Was hätte zurückgegeben werden müssen? Man könnte sagen Ringo
da er sich offenbar zuletzt angemeldet hat, aber das ist reine Interpretation. Meiner Meinung nach hätten beide zurückgeschickt werden müssen, da man anhand der verfügbaren Daten nicht eindeutig entscheiden kann.
Diese Abfrage entspricht also den Anforderungen:
SELECT users.*
FROM
logins JOIN
users ON
logins.user_id = users.user_id AND
logins.login_date = (
SELECT max(logins.login_date)
FROM
logins JOIN
users ON logins.user_id = users.user_id)
Als Alternative bieten einige DBMS spezielle Funktionen an (z. B. Microsoft SQL Server 2005 führt TOP n WITH TIES ... ORDER BY key
(vorgeschlagen von gbn ), RANK
y DENSE_RANK
für genau diesen Zweck).
Wenn Sie SO z.B. nach ROW_NUMBER
finden Sie zahlreiche Lösungen, die die Verwendung von Ranking-Funktionen vorschlagen und es versäumen, auf die möglichen Probleme hinzuweisen.
Frage: Welche Ratschläge sollten gegeben werden, wenn eine Lösung vorgeschlagen wird, die eine Ranking-Funktion beinhaltet?