mmofacts.com

SQL: Rang / PLatzierung

gepostet vor 17 Jahre von azamaroth
Hiho,
ich hoffe jemand kann mir bei meinem Problem helfen:
Ich habe aus einer SQL-Datenbank eine Tabelle mit mehreren Werten, möchte daraus Platzierungen wissen. Z.B. Wer hat am meisten Punkte, wer hat die 2. meisten Punkte etc.
Gibt es dafür eine SQL Funktion, aus der ich diesen Wert erhalte. Möchte also der SQL Funktion sagen, welchen Rang ich wissen möchte, und der Datensatz wird mir zurückgegeben.
Hoffe mir kann jemand helfen...
gepostet vor 17 Jahre von Korporal
Hi,
ich würde dir eine Schleife empfehlen die du alle X Stunden ausführst, zum Beispiel mit Hilfe eines Cronjobs (wird das beste sein).
Dort zählst du halt die Platzierungen und speicherst diese extra ab, oder du machst es halt in Echtzeit und baust es gleich so in die Highscore ein.
gruß
gepostet vor 17 Jahre von ThaDafinser
hmm ein dürftige angabe!
schreib doch mal deine tabellen ein bisschen nieder!
bzw. suchst du ev. nach SUM(), COUNT() usw?!
gepostet vor 17 Jahre von Fornax
Klingt nach folgendem für z.B. "Platz 2 bekommen"
SELECT id, name FROM user ORDER BY punkte LIMIT 2,0
Bei der Genauen Limit-Angabe bin ich mir gerade unsicher, aber das müsste so sein.
gepostet vor 17 Jahre von Kampfhoernchen
Je nach dem wie viele datensätze kannst du das auch mit ORDER BY punke DESC und LIMIT 100,100 oder so Lösen.
Falls es viele Datensätze sind, hilft nur der Cron, solange es keine Oracle-Tabelle ist (die kann irgendwas mit "rownum").
Gruß
gepostet vor 17 Jahre von HSINC
order by, limit, count und ein sinnvolles where sollten das ohne probleme machen
gepostet vor 17 Jahre von shadows
Oder ab SQL Server 2005:

SELECT row_number() OVER (ORDER BY Punkte desc) AS Rang
FROM tabelle
gepostet vor 17 Jahre von Todi42
Wenn ich Dich richtig verstanden habe, suchst Du halt neben dem Sortierkriterium auch die laufende Nummer. Ich habe das mal eine Zeit lang mit standart SQL probiert, und des auch mit externer Hilfe nicht hin bekommen. Mit Oracle würde es gehen.
gepostet vor 17 Jahre von ThaDafinser
ich würde sagen die frage muss neu gestellt werden.
man sieht ja das jeder was anderes hier interpretiert
gepostet vor 17 Jahre von dgame
Meine Interpretation:
Wenn du etwas dynamisches suchst, das für den Moment den Rang anzeigen soll:
$rang = mysql_query("SELECT id FROM tabelle WHERE level > deinem Kriterium");
$rang = mysql_num_rows($rang) + 1;
Dann hast du den Rang.
Die Lösung ist aber 100%ig nicht die Optimalste. Normalerweise würde man das mit SUM() machen, dazu wurden ja auch schon Beispiele gegeben, also einfach kombinieren.
mfg
dgame
gepostet vor 17 Jahre von azamaroth
Also,
danke erstmal für eure Antworten, werde da mal was ausprobieren.
Trotzdem nochmal der Hintergrund:
in der Tabelle gibt es z.B. den NAMEN und PUNKTE.
Ich möchte da einmal wissen, wer ist der 1., 2. und 3. Und das möglichst mit SQL. Ich dachte da würde es vielleicht eine Funktion geben, der ich wie z.B. in Excel mit der Funktion RANG (glaube ich), einen Rang angebe, und ich dann Namen und Punkte erhalte.
gepostet vor 17 Jahre von KoMtuR
Original von Kampfhoernchen
Je nach dem wie viele datensätze kannst du das auch mit ORDER BY punke DESC und LIMIT 100,100 oder so Lösen.
Falls es viele Datensätze sind, hilft nur der Cron, solange es keine Oracle-Tabelle ist (die kann irgendwas mit "rownum").
Gruß

@azamoth
Da steht es drin, wie du das machst. Du hast nun kein RANG(), aber im Limit gibst du den Rang an und bekommst dann den User + Punkte
gepostet vor 17 Jahre von Macavity
in der Tabelle gibt es z.B. den NAMEN und PUNKTE.
Ich möchte da einmal wissen, wer ist der 1., 2. und 3. Und das möglichst mit SQL. Ich dachte da würde es vielleicht eine Funktion geben, der ich wie z.B. in Excel mit der Funktion RANG (glaube ich), einen Rang angebe, und ich dann Namen und Punkte erhalte.

Du hast aber schon mal was mit MySQL gemacht oder? Prinzipiell hast du bisher diverse Lösungsvorschläge bekommen. ^^
gepostet vor 17 Jahre von ThaDafinser
das wundert mich jetzt ja langsam auch Oo
wenn man ein browsergame schreiben will, sollte man doch da wenigstens ne ahnung haben.
wenn man da probleme hat, was macht man denn mit den tausenden joins?^^
gepostet vor 17 Jahre von raufaser

$pruefe_name = "Spielername";
$platz = 1;
$dbresult = mysql_query( "SELECT name FROM player WHERE 1 ORDER BY punkte DESC;" );
while( $check = mysql_fetch_row( $dbresult ) )
{
if( $check[ 0 ] == $pruefe_name )
break;
$platz++;
}
mysql_free_result( $dbresult );
echo "Der Spieler $pruefe_name ist auf Platz $platz";

PS: Bitte jetzt nicht rummaulen, wie unsauber das ist. Weiß ich selbst. Aber irgendwer muss azamaroth wohl mal ein konkretes Beispiel liefern.
(Ich nutze eine ähnliche Funktion auch für mein Spiel, allerdings wird der Platz eines Spielers nur alle 6 Stunden ermittelt und gespeichert... das ist im Rahmen.)
gepostet vor 17 Jahre von Nightflyer
Ich wiederspreche hier mal raufaser. Eine Schlaufe ist immer Blödsinn wenn man sie umgehen kann:
 $pruefe_name = "Spielername";

$dbresult = mysql_query( "SELECT COUNT(`id`) AS num FROM player ORDER BY punkte DESC LIMIT 0,(SELECT `punkte` FROM `player` WHERE `name`='".mysql_real_escape_string($pruefe_name)."');" ) or die( mysql_error() );
echo "Der Spieler ".$pruefe_name." ist auf Platz ".mysq_result($dbresult, 0, 0);

gepostet vor 17 Jahre von raufaser
Dein Beispiel funktioniert bei mir nicht... und es ergibt auch keinen Sinn.
gepostet vor 17 Jahre von Lubi
Als Alternative zu Nightflyers Variante (sollte aber sinnvolle Werte ergeben)

$spielername = 'Test';
$sql_qry = "SELECT p.name, p.punkte,
(SELECT COUNT(*) + 1 FROM players WHERE punkte > p.punkte) rang
FROM player p WHERE Name = '$spieler_name'";
$dbresult = mysql_result($sql_qry);
if (mysql_num_rows($dbresult) > 0) {
echo "Der Spieler $spieler_name ist auf Platz " . mysql_result($dbresult, 0, 'rang') . " und hat " . mysql_result($dbresult, 0, 'punkte') . " Punkte.";
}
gepostet vor 17 Jahre von Macavity
Scheisse jetzt schreib ich den Beitrag nochmal weil GN irgendwas von einem falschen Link gefaselt hat
Ziel: Anzeige der Plätze 10 bis 20

$start = 10;
$playersPerPage = 10;
$sql = "SELECT name,punkte FROM charaktere WHERE punkte > 0 ORDER BY punkte DESC LIMIT ".($start-1).",10";
$result = mysql_query($sql);
$i = $start;
while($row = mysql_fetch_array($result)){
$name = $row["name"];
$punkte = $row["punkte"];
echo "\n
Platz $i: Charakter $name - $punkte Punkte ";
$i++;
}
mysql_free_result( $result );
Semikolonfehler oder ähnliches kann jeder selbst korrigieren, habe es nicht getestet aber müsste funktionieren... ist im Endeffekt ja nur eine Zusammenfassung der ersten Antworten.
Und nein ich würde keine deutschen Spaltennamen benutzen, nur hier für unsere nicht-englisch-fähigen Mitentwickler
gepostet vor 17 Jahre von raufaser
Lubis Lösung ist gut.
Leider muss ich doch meinen Loop machen, weil ich bei mir nicht nur ein Kriterium habe, sondern 2.
Es gibt einmal den Level des Spielers und die Erfahrungspunkte.
Aber wenn man nur ein Feld für die Punktebewertung hat, ist Lubis Lösung optimal, wenn man herausfinden will, auf welchem Rang ein Spieler in der Rangliste ist.
Gruß,
Marc
gepostet vor 17 Jahre von Macavity
Leider muss ich doch meinen Loop machen, weil ich bei mir nicht nur ein Kriterium habe, sondern 2.

Verstehe nicht wo da das Problem ist. Du kannst doch wunderbar nach 2 Feldern sortieren?
gepostet vor 17 Jahre von raufaser
Mit einem ORDER BY in ein einem Loop ist das auch kein Problem, aber mit einem COUNT über ein SUBSELECT geht's leider nicht, was an den Werten in den Feldern liegt.
Beispiel:
Spieler Position 1:
Level: 14 XP: 5302
Spieler Position 2:
Level: 13 XP: 15347
Bei solchen Werten haut das mit dem COUNT leider nicht hin, weil die WHERE Bedingung da ja zählt und nicht die ORDER.
Beispiel SQL:

SELECT p.name,
(SELECT COUNT(uid) FROM player AS c WHERE c.level>=p.level AND c.xp>=p.xp) AS rang
FROM player AS p
WHERE p.name='Raufaser';
(XP = Erfahrungspunkte bis zur nächsten Stufe, Level = Stufe)
Oder gibt's noch eine andere Möglichkeit, die ich nicht sehe?
gepostet vor 17 Jahre von Drezil
wäre es nicht so sinniger?

SELECT p.name,
(SELECT COUNT(uid) FROM player AS c WHERE (c.level=p.level AND c.xp>=p.xp) OR c.level > p.level) AS rang
FROM player AS p
WHERE p.name='Raufaser';
gepostet vor 17 Jahre von Lubi
@drezil:
Sollte so gehen (außer, dass du Fehler bei gleicher Punktzahl bekommst)

SELECT p.name,
(SELECT COUNT(uid) + 1 FROM player AS c WHERE (c.level = p.level AND c.xp > p.xp) OR c.level > p.level) AS rang
FROM player AS p
WHERE p.name='Raufaser';
So sollte auch das Problem beseitigt sein... (damit erhalten alle EXAKT gleich-bepunkteten den gleichen Rang und nicht je nachdem, wer die Tabelle aufruft von den gleich-rangigen nen unterschiedlichen Rang ;-) )
gepostet vor 17 Jahre von raufaser
Hab's gerade getestet: So ist es perfekt. Danke Drezil, danke Lubi. Das ich da nicht selbst drauf gekommen bin... Wenn man es sieht ist es so klar...
Ich werde meine Schleife damit ablösen.
Gruß,
Marc

Auf diese Diskussion antworten