Hans: mysql - Problem mit DISTINCT und ORDER BY

Hallo,
ich habe ein Onlinegame mit einer Highscore, die in einer Tabelle gespeichert wird ("highscore"). Dann gibt es noch eine weitere Tabelle mit den Daten der Spieler ("teilnehmer"). Die spielerID der Tabelle "highscore" ist hier mit der id in der Tabelle "teilnehmer" verknüpft.

Ich möchte mir jeden Monat die besten 100 Spieler ausgeben lassen. Die Ausgabe soll zuerst nach Punkten (höchste zuerst) und dann nach Zeitverbrauch (niedrigster zuerst) geordnet werden. Folgende Abfrage funktioniert auch ganz gut:
----
SELECT highscore.punkte, highscore.zeitverbrauch,
teilnehmer.vorname, teilnehmer.nachname, teilnehmer.strasse, teilnehmer.ort, teilnehmer.email, highscore.datum
FROM teilnehmer, highscore
WHERE highscore.eintragzeit < '2007-03-01'
AND highscore.eintragzeit >= '2007-01-01'
AND highscore.spielerID = teilnehmer.id
ORDER BY highscore.punkte DESC , highscore.zeitverbrauch ASC
LIMIT 0 , 100
----

Da viele Spieler mehrmals spielen, habe ich deren Namen immer mehrfach in meiner Ausgabe. Deshalb habe ich mal DISTINCT und MAX ausprobiert, um mir jeden Spieler nur einmal anzuzeigen und die maximale Punktzahl des Spielers zu ermitteln:
----
SELECT DISTINCT highscore.spielerID,
MAX(highscore.punkte) AS punkte,
highscore.zeitverbrauch,
teilnehmer.vorname, teilnehmer.nachname, teilnehmer.strasse, teilnehmer.ort, teilnehmer.email, highscore.datum
FROM teilnehmer, highscore
WHERE highscore.eintragzeit < '2007-03-01'
AND highscore.eintragzeit >= '2007-01-01'
AND highscore.spielerID = teilnehmer.id
GROUP BY highscore.spielerID
ORDER BY punkte DESC , highscore.zeitverbrauch ASC
LIMIT 0 , 100
----

Mein Problem:
Jetzt werden mir die Spieler auch nur einmal angezeigt, und die Sortierung nach Punkten stimmt auch. Allerdings funktioniert jetzt natürlich die Sortierung nach Zeitverbrauch nicht mehr. In der Ausgabe wird mir nämlich nicht der Zeitverbrauch an der Stelle von MAX(highscore.punkte) gezeigt, sondern offensichtlich der letzte der in der Tabelle steht.

Meine Frage:
Wie bekomme ich eine Ausgabe, in der jeder Spieler nur einmal erscheint,die mir die maximale Punktzahl des Spielers anzeigt und den Zeitverbrauch bei dieser Punktzahl und die dann noch nach Punkten und Zeitverbrauch geordnet ist?

Vielen Dank und Grüße

Hans

  1. yo,

    Wie bekomme ich eine Ausgabe, in der jeder Spieler nur einmal erscheint,die mir die maximale Punktzahl des Spielers anzeigt und den Zeitverbrauch bei dieser Punktzahl und die dann noch nach Punkten und Zeitverbrauch geordnet ist?

    SELECT DISTINCT (SELECT MAX(highscore.punkte) FROM highscore h2 WHERE h2.spielerID = t.id) AS high,
    highscore.zeitverbrauch, teilnehmer.vorname, teilnehmer.nachname, teilnehmer.strasse, teilnehmer.ort, teilnehmer.email, highscore.datum
    FROM teilnehmer t
    INNER JOIN highscore h1 ON h1.spielerID = t.id
    WHERE h1.eintragzeit BETWEEN '2007-01-01' AND '2007-01-31'
    ORDER BY high DESC, h1.zeitverbrauch
    LIMIT 0, 100

    Ilja

    1. yo,

      habe vergessen, bei der ausgabe der spalten, die tabellen-asliasnamen zu verwenden. die abfrage geht ab mysql version 4.1+

      Ilja

      1. yo,

        habe vergessen, bei der ausgabe der spalten, die tabellen-asliasnamen zu verwenden. die abfrage geht ab mysql version 4.1+

        Ilja

        Hallo und vielen Dank!

        Ich hoffe, ich habe die aliasnamen richtig verwendet:
        ----
        SELECT DISTINCT (
        SELECT MAX(h2.punkte)
        FROM highscore h2
        WHERE h2.spielerID = t.id
        ) AS high, h1.zeitverbrauch, t.vorname, t.nachname, t.strasse, t.ort, t.email, h1.datum
        FROM teilnehmer t
        INNER JOIN highscore h1 ON h1.spielerID = t.id
        WHERE h1.eintragzeit
        BETWEEN '2007-03-01'
        AND '2007-03-31'
        ORDER BY high DESC , h1.zeitverbrauch
        LIMIT 0 , 100
        ----

        Die Sortierung ist jetzt richtig, allerdings erscheinen die Spielernamen jetzt nicht nur einmal sondern wieder mehrfach.

        Wie kann ich das noch lösen?

        Viele Grüße

        Hans

        1. yo,

          Die Sortierung ist jetzt richtig, allerdings erscheinen die Spielernamen jetzt nicht nur einmal sondern wieder mehrfach.

          das liegt an den h1 spalten, die ich übersehen habe und die mit ausgegeben werden. es liegt ein fachliches problem vor, dass du erst einmal entscheiden musst, dann kann ich dir eine lösung sagen. was passiert, wenn ein spieler die gleiche punktzahl in der gleichen zeit geschafft hat. soll er dann zweimal angezeigt werden oder nur einmal  und wenn nur einmal, welcher der beiden datensätze ?

          Ilja

          1. yo,

            Die Sortierung ist jetzt richtig, allerdings erscheinen die Spielernamen jetzt nicht nur einmal sondern wieder mehrfach.

            das liegt an den h1 spalten, die ich übersehen habe und die mit ausgegeben werden. es liegt ein fachliches problem vor, dass du erst einmal entscheiden musst, dann kann ich dir eine lösung sagen. was passiert, wenn ein spieler die gleiche punktzahl in der gleichen zeit geschafft hat. soll er dann zweimal angezeigt werden oder nur einmal  und wenn nur einmal, welcher der beiden datensätze ?

            Ilja

            Stimmt natürlich, das kann ja theoretisch passieren. Der Spieler sollte am besten genau einmal erscheinen, auch bei genau gleicher Punktzahl und Zeit. Der eingetragene Datensatz ist dann im Prinzip egal, was einfacher ist, hauptsache der Spielername mit Punkten und Zeit stehen da :-)

            Danke
            Hans

            1. yo,

              das problem ist ein wenig komplizierter, weil wir das datum mitschleifen müssen.

              SELECT h1.punkte, h1.zeitverbrauch, t.vorname, t.nachname, t.strasse, t.ort, t.email, h.datum
              FROM teilnehmer t
              INNER JOIN highscore h1 ON h1.spielerID = t.id
              WHERE h1.id =
              (SELECT MIN(h2.id)
               FROM highscore h2
               WHERE h2.spielerID = t.id
               AND h2.eintragzeit BETWEEN '2007-01-01' AND '2007-01-31'
               AND h2.punkte = (SELECT MAX(h3.punkte)
                                FROM highscore h3
                                WHERE h3.spielerID = t.id
                                AND h3.eintragzeit BETWEEN '2007-01-01' AND '2007-01-31'
                               )
               AND h2.zeitverbrauch = (SELECT MIN(h3.zeitverbrauch)
                                       FROM highscore h3
                                       WHERE h3.spielerID = t.id
                                       AND h3.eintragzeit BETWEEN '2007-01-01' AND '2007-01-31'
                                       AND h3.punkte = (SELECT MAX(h4.punkte)
                                                        FROM highscore h4
                                                        WHERE h4.spielerID = t.id
                                                        AND h4.eintragzeit BETWEEN '2007-01-01' AND '2007-01-31'
                                                       )
                                      )
              )
              ORDER BY high DESC, h1.zeitverbrauch
              LIMIT 0, 100

              ich kann die abfrage nicht testen, können als kleine tippfehler drinn sein. scheint auf den ersten blick ein wenig "oversized" zu sein. aber auf den ersten blick fällt mir nichts anderes ein....schau mal, ob sie überhaupt geht.

              Ilja