Rang mit MySQL bei einzelauslese unter Verwendung von Order definieren

Marius Heil

Erfahrenes Mitglied
Reichlich komplizierter Titel^^
Im Prinzip geht es mir darum:
Ich habe eine Highscoreliste, sagen wir einmal 1000 user, da gibts natürlich auch welceh drutner, die die gleiche Punktezahl haben. Soweit so gut, jetzt bekommt jeder User in seinem Profil seine Persönlichen Daten angezeigt, bestehend aus:
Punkte:
Rang:
Titel:
Geld:
Gut, Punkte und Geld sind eifnach auslesbar und den Titel, da include ich einfach eine rang.php und geb dann den Titel je nach Punktezahl aus, der Rang allerdings bereitet mir größere Probleme. Ich hab:
User Punkte Geld
und noch allerlei sonstiges. Wenn ich nun den Username hab, wie bekomm ich dann den Rang des Users in der Gesamtliste raus?
Alles in PHP einlesen und durchnummerieren kann ich ncith machen, da macht der Server nicht mit. Es müsste also von MySQl ne Funktion geben, dass ich irgendwie ORDER oder so benutzen könnte und dann die Cursorposition in der Tabelle rausbekommen könnte.


Marius
 
Die Funktion, die du suchst lautet WHERE.

PHP:
$sql="SELECT * FROM tabelle WHERE name = 'Marius'";

Dieses Beispiel würde also alle Zeilen auslesen, wo das Feld name den Wert Marius hat.

mfg
forsterm
 
Zuletzt bearbeitet:
Meine Annahmen:
Der Rang ermittelt sich wie folgt:
User mit mehr Punkten stehen weiter vorne. Sind die Punkte gleich, steht der User weiter vorne, der mehr Geld hat.
Bei Punktegleichheit und Geldgleichheit erhalten die User denselben Rang. Die Ränge, die dadurch überlagert werden fallen weg.
1 ist der beste Rang.
Beispiel:
1. User C, Punkte=100 Geld=20
2. User D, Punkte=100 Geld=10
2. User A, Punkte=100 Geld=10
4. User B, Punkte=90 Geld=100
Code:
SELECT 
(COUNT(*)+1) AS `Rang` 
FROM tabelle 
WHERE `Punkte`<[PunkteDesBetrachtetenUsers]
OR (
  `Punkte`=[PunkteDesBetrachtetenUsers]
  AND `Geld`<[GeldDesBetrachtetenUsers]
)
Du kannst dieses Query einzeln nach dem Auslesen des Users mit PHP erzeugen, indem Du anstelle der eckigen Klammern (und dem, was da drin steht) die entsprechenden Werte des abgefragten Users einträgst oder Du schreibst dieses Query als Subquery in Deine eigentliche Abfrage mit den entsprechenden Feldnamen Deiner Tabelle.

Ich habe das Query nicht getestet, aber ein Versuch ist es wert.

Gruß hpvw
 
@forsterm: Nein, diese Funktion suche ich nicht ;-)
Damit würde ich zwar den User bekommen, was ich im Prinzip auch will, ich mag aber außerdem seinen Rang bekommen und der Muss nach Punkten sein.
@hpvw: Mhhh, sorry, aber ich kam nciht ganz klar damit, ich ahb auch mal das Probiert:
SELECT (
COUNT( * ) +1
) AS `Rang`
FROM user
WHERE `Username` = "DUDELDUMM"
ORDER BY Username DESC
LIMIT 0 , 30

Ich ahb gehofft, während MySQL die Daten druchgeht, geht es die nummeriert durch und sagt mir dann den dazugehörigen Rang, ich les aber ja nur ein Feld des Users aus und dazu mag ich ja den zugehörigen Rang.
Ich bin am überlegen, dass ich ne zusätzliche Spalte mit Rang anlege und die per Cronjob jeden Tag mal aktualisiere....
Ich bin mir nämlich ziemlich sicher, dass das einige andere Onlinespiele auch machen.


Marius
 
Was war denn das Ergebnis oder die Fehlermeldung?
An welcher Stelle kommst Du nicht klar?

Das was Du eben geschrieben hast wird nicht funktionieren.

MySQL hat meines Wissens keinen Zähler, während er die Tabelle durchsucht.
 
So, ich habe mal ein Testtabelle aufgesetzt. Hier der DUMP von phpMyAdmin
Code:
-- phpMyAdmin SQL Dump
-- version 2.6.2-pl1
-- http://www.phpmyadmin.net
-- 
-- Host: localhost
-- Erstellungszeit: 28. Juni 2005 um 19:11
-- Server Version: 4.1.10
-- PHP-Version: 5.0.3
-- 
-- Datenbank: `testdb`
-- 

-- --------------------------------------------------------

-- 
-- Tabellenstruktur für Tabelle `userrang`
-- 

CREATE TABLE `userrang` (
  `id` int(11) unsigned NOT NULL auto_increment,
  `name` varchar(255) NOT NULL default '',
  `punkte` int(11) NOT NULL default '0',
  `geld` int(11) NOT NULL default '0',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;

-- 
-- Daten für Tabelle `userrang`
-- 

INSERT INTO `userrang` VALUES (1, 'User A', 100, 10);
INSERT INTO `userrang` VALUES (2, 'User B', 90, 100);
INSERT INTO `userrang` VALUES (3, 'User C', 100, 20);
INSERT INTO `userrang` VALUES (4, 'User D', 100, 10);
Folgendes Query ermittelt die Daten aller User:
Code:
SELECT 
t1.`id`, 
t1.`name`, 
t1.`punkte`, 
t1.`geld`,
(SELECT 
  (COUNT(*)+1)
  FROM userrang AS t2
    WHERE t2.`Punkte`>t1.`punkte`
    OR (
      t2.`Punkte`=t1.`punkte`
      AND t2.`geld`>t1.`geld`
  )
) AS `Rang`
FROM userrang AS t1
ORDER BY `Rang`
Ergebnis:
Code:
id name    punkte geld Rang
 3 User C     100   20    1
 1 User A     100   10    2
 4 User D     100   10    2
 2 User B      90  100    4
Und dieses Query ermittelt die Daten für einen bestimmten User (hier den mit der id 2):
Code:
SELECT 
t1.`id`, 
t1.`name`, 
t1.`punkte`, 
t1.`geld`,
(SELECT 
  (COUNT(*)+1)
  FROM userrang AS t2
    WHERE t2.`Punkte`>t1.`punkte`
    OR (
      t2.`Punkte`=t1.`punkte`
      AND t2.`geld`>t1.`geld`
  )
) AS `Rang`
FROM userrang AS t1
WHERE t1.`id`=2
ORDER BY `Rang`
Ergebnis: User B steht auf Rang 4.
Wenn Du nur nach Punkten gehst, kannst Du den OR-Teil des Subselect weglassen:
Code:
SELECT 
t1.`id`, 
t1.`name`, 
t1.`punkte`, 
t1.`geld`,
(SELECT 
  (COUNT(*)+1)
  FROM userrang AS t2
    WHERE t2.`Punkte`>t1.`punkte`
) AS `Rang`
FROM userrang AS t1
ORDER BY `Rang`
Im ersten Post hatte ich übrigends einen Fehler, da ich Größer- und Kleiner-Zeichen verwechselt habe.

Gruß hpvw
 
Mhhh, also vielen Dank erstmal für die Arbeit, ich bins mal durchgegangen, beim ersten Mal hab ich noch nciht alles kapiert. Ich werd mich nach dem Essen nochmal dransetzen.


Marius
 
Also das scheint wirklich perfekt zu funktionieren, allerdings hab ich irgendwie ein Problem mit dem kapieren, erstens komm ich nicht ganz hitner die Funktionsweise und dann weiß ich auch nciht, was du da als mit:
t1. und t2 und so machst.
Wenn ich die Highscoreliste so aufbau, ist das arg Recoursenintensiv?
So eine Abfrage gin jetzt wirklich sehr kurz, wie ist das, wenn ich dann eine größere usertabelle hab?

Vielen Dank, dass du dir so viel Mühe gegeben hast.

Marius
 
Marius Heil hat gesagt.:
t1. und t2 und so machst.
Da ich in dem Subquery auf dieselbe Tabelle zugreife habe ich Aliastabellennamen vergeben, um über diese eindeutig zu kennzeichnen, aus welchem Query ich die Tabelle meine.

Marius Heil hat gesagt.:
Wenn ich die Highscoreliste so aufbau, ist das arg Recoursenintensiv?
So eine Abfrage gin jetzt wirklich sehr kurz, wie ist das, wenn ich dann eine größere usertabelle hab?
Ich denke wesentlich ressourcensparender wird es nicht gehen. Es sind ja "nur" Ganzzahlvergleiche und count. Count ist in MySQL relativ schnell.

Für die Gesamtuserliste könnte es logischerweise Probleme geben, wenn Du jedoch nur einen einzelnen User in der Profil-Seite darstellst sehe ich keine Probleme.

Wenn Du mehr wissen willst, musst Du Deine Tabelle testweise mit ein paar tausend Datensätzen füllen und die Zeit stoppen.

Gruß hpvw
 
So, danke nochmal, was muss ich machen, wenn ich nun auch noch nach Username (Und Teilnamen) sowei Rang und Punkte suchen will? Nach onlinestatus sortieren wäre das nächste. Damit mag ich dann einen kleinen Teil der Ranglsite zeigen, 15 User, die man eben suchen kann oder nach Kriterien ordnen kann...
Ist arg kompliziert.
Tut mir Leid, dass ich so viele Fragen stell, bin am überelgen, ob ich per Cronjob die Liste einmal täglich ordnen soll, dann müsst ich dich nciht mit den Fragen belästigen^^


Marius
 
Zuletzt bearbeitet:
Zurück