Ich habe ein blödes kleines Spiel geschrieben und möchte eine Art Leaderboard-Website haben.
Normalerweise sind die Bestenlisten auf 10 oder 20 Topspieler begrenzt, aber ich dachte, es wäre nett, wenn ich für jeden Spieler seine Top-Punktzahl aufnehmen könnte . Dann könnte ich immer ihren weltweiten Rang anzeigen.
Ein einfaches Schema wie:
%Vor%Würde die minimale Menge an Informationen speichern, die ich brauche - 1 Eintrag pro Benutzer mit der besten Punktzahl.
Meine Frage dreht sich darum, wie man die Position einer Person auf der Rangliste effizient bestimmen kann. Die allgemeine Idee ist, dass ich ihre Position in der Liste von:
zurückgeben möchte %Vor%Aber diese Abfrage auszuführen und dann die Liste linear zu durchsuchen, erscheint mir aus der Sicht der DB-Performance etwas lächerlich. Trotzdem habe ich Schwierigkeiten, mir eine Abfrage / ein Schema vorzustellen, die eine schnelle Operation ermöglichen würden.
Irgendwelche Ideen?
(Ich würde es vorziehen, das DB-Schema zu behalten und generische Anfragen abzufragen (nicht an einen Anbieter gebunden.) Aber wenn ein Hersteller dies einfach macht, bin ich glücklich, entweder MS SQL oder MySQL zu verwenden.
Ab SQL Server 2005 können Sie das RANK()
Funktion, um den Rang für jeden Benutzer basierend auf seiner Punktzahl zurückzugeben
Wenn Sie mehr als einen Typ von "Spieltyp" hatten, können Sie dies in die Tabelle Leaderboard aufnehmen und die PARTITION BY
-Klausel in der Funktion RANK
verwenden, um die Rangfolge für jeden Spieltyp zu bestimmen.
Die naheliegende Option wäre, einen Index für "Score" zu erstellen, was völlig in Ordnung ist. (Es klingt, als ob Sie zwei Werte beibehalten möchten - kumulative Punktzahl und High-Water-Punktzahl - oder ich missverstehe sonst?)
Wenn Sie nicht Zehntausende von Benutzern erwarten, sollten selbst Tabellen-Scans in einer Tabelle mit diesen vielen Datensätzen kein großes Problem darstellen.
Sieht so aus, als wollten Sie das abfragen:
%Vor%Dies gibt die Bestenliste mit 1 Eintrag für jeden Benutzer zurück.
BEARBEITEN SIE UNTEN: Ich sehe in dem Kommentar, dass Sie den Rang sehen wollen, nicht das Ergebnis. dafür kenne ich die ANSI SQL Antwort nicht, aber datenbankspezifisch:
In MySQL:
%Vor%In Oracle können Sie die RANK-Anweisung verwenden.
In SQL Server 2005 erledigt Rank () ziemlich genau die Aufgabe für Sie. Aber wenn du Millionen von Datensätzen hast, dann rangiere sie in Echtzeit, wenn sich die zugrunde liegenden Werte ändern, wird das Performance-Schwein.
Ich habe versucht, eine indexierte Ansicht oberhalb der ausgewählten Abfrage zu erstellen ... (die gewählte Antwort in diesem Thread), aber Sql 2005 ließ mich das nicht erstellen, weil Sie keine Unterabfragen, Selbstreferenz in einer indizierten Sicht verwenden können.
Unsere Problemumgehung besteht also darin, die Rangliste allabendlich mit der Funktion Row () zu aktualisieren. Um das Blockieren während dieses Updates zu vermeiden, bewahren wir 2 Kopien der Rangliste auf, die aktualisiert und in der Anwendung verwendet werden. Wir haben eine RankingView, die zu jeder Zeit auf die aktive Rangliste zeigt.
Ich würde gerne wissen, ob es eine Lösung für Echtzeit-Ranking-Update für wirklich große Tabellen gibt?
Ich habe über das select nachgedacht "Anzahl (*) + 1 als Rang vom Leaderboard auswählen wo Punkt & gt; (Wählen Sie den Punktestand aus der Bestenliste, wo userid =?) "
Denken Sie an die folgende Situation: Spieler 1, 100 Punkte Spieler 2, 100 Punkte Spieler 3, Ergebnis 50
Mit diesem SQL wäre der Rang von Spieler 3 3, wobei die richtige Antwort 2 sein sollte, weil Spieler 1 und Spieler 2 an der ersten Position gebunden sind. Die Aggregatfunktion count () berücksichtigt in diesem Fall 2 Datensätze mit Score-Spalte & gt; 50.
Um diesen Fall zu behandeln, denke ich, dass die richtige Option darin besteht, eine Gruppe zu bilden, so dass wiederholbare Werte der Punkte als eine einzige Rangposition behandelt werden:
%Vor%