(MySQL) richtige Anweisung gesucht
Andreas Schigold
- datenbank
Hallo liebe Forummer,
ich habe da mal ein Anliegen. Bei meinem Spiel unter http://schigold.de/ habe ich ja eine Highscoreliste eingebaut. Nun tragen sich ja viele ein und auch viele mehrfach. Ist auch so gewollt. Damit jemand mit weniger Punkten sich jetzt nicht so weit unten suchen muß, habe ich eine zweite Tabelle mit dem "besten Ergebnis" eines Jeden hingesetzt.
Da ist aber ein Fehler drin:
Nimmt man zum Beispiel den 1. Platz von "Stuvar", dann sieht man links richtig stehen:
1. 84 6.6 Stuvar
in der rechten Tabelle aber steht nun quasi der erste Eintrag von Stuvar mit seinem höchsten Ergebnis gekoppelt, das ist aber falsch.
sein erster Eintrag war (13 4.2 Stuvar) plus sein bestes Ergebnis (84 6.6 Stuvar) ergibt die falsche Anzeige von (84 4.2 Stuvar)
für die linke Tabelle ist die SELECT einfach:
select laenge, schnitt, name from highscore order by laenge desc;
für die rechte Tabelle ist die SELECT momentan:
select max(laenge) as lang, schnitt, name from highscore group by name order by lang desc;
Aber wie müßte sie richtig heißen, damit eben 84 6.6 Stuvar angezeigt wird?
Bin für jeden Beitrag dankbar, und seien es nur tröstende Worte daß es nicht geht oder der Vorschlag auf Oracle umzusteigen. Die richtige SQL-Anfrage wäre mir natürlich lieber ;-)
Gruß,
Andreas
PS: ich hoffe, daß mein Spiel keinen zu sehr von der Arbeit abhält *g*
ehrlcih gesagt, finde ich da nirgends ein spiel auf deiner Page, oder war das ein lustiger trick um traffic auf deine Page zu bekommen :o). Posta mal, wo dein spiel ist, dann kann ich es vielleicht besser nachvollziehen
-----------------------------
http://www.script-fabrik.de
jetzt neu mit Quiz
Hi Script-fabrik,
sorry, war ein Fehler aus der Gewohnheit. Die angegebene Seite ist ja meine HP. Das Spiel ist nicht durchgelinkt und liegt unter
Aber ich war natürlich in der Zwischenzeit nicht untätig und habe nach langem verzweifelten Suchen einen ganz versteckten Link auf mysql.com gefunden:
http://www.mysql.com/doc/e/x/example-Maximum-column-group-row.html
Dort ist halt eine etwas umständliche Lösung angegeben, aber geht wohl in MySQL nicht besser. Schade, das wär nämlich ein echtes Argument für subselects, denn eine temporary table kann doch nicht das Gelbe vom Ei sein.
Problem war, daß zwar die höchste Länge eines jeden Spielers ausgegeben wurde und auch der richtige Name, aber die "durchschnittliche Längenzunahme je 10 sec" war eben nicht die passend zur größten Länge, sondern die passend zum (zeitlich) ersten Eintrag.
Naja, auf der MySQL-Seite ist ja die Sub-Select angegeben, die das Ziel sein soll.
Trotzdem danke für's gucken auf meiner Hauptseite, ich hoffe, ich kann Euch mit meinem kleinen Spiel ein wenig dafür entschädigen. (Diesmal habe ich die Links vorm Absenden nochmal angeschaut, sollte jetzt hinhauen)
Gruß
Andreas
Hi Andreas,
select max(laenge) as lang, schnitt, name from highscore
group by name order by lang desc;
ich habe Dein DB-Schema nicht ganz verstanden.
Aber Dein Problem klingt so, als würdest Du auch auf der rechten Seite
_einen_ Datensatz aus Deiner Tabelle holen wollen.
Das tust Du aber nicht - Du mischst gespeicherte und berechnete Werte
(weil Du "max" verwendest).
Was Du tatsächlich willst, ist,
Ich weiß im Moment nicht, ob diese doppelte Sortierung mit einem einzigen
SELECT geht; es kann sein, daß dafür ein SubSelect erforderlich wäre, was
mySQL nicht direkt unterstützt.
In diesem Fall könntest Du aber den ersten SELECT in eine temporäre Tabelle
lenken und aus dieser mit dem zweiten die endgültige Sortierung heraus-
fischen.
Viele Grüße
Michael
Hi Andreas,
select max(laenge) as lang, schnitt, name from highscore
group by name order by lang desc;
ich habe Dein DB-Schema nicht ganz verstanden.
Aber Dein Problem klingt so, als würdest Du auch auf der rechten Seite
_einen_ Datensatz aus Deiner Tabelle holen wollen.
Das tust Du aber nicht - Du mischst gespeicherte und berechnete Werte
(weil Du "max" verwendest).
Was Du tatsächlich willst, ist,
- zuerst die Datensätze nach Spielern zu gruppieren,
- davon aber jeweils nur den einen Datensatz mit dem höchsten Wert zu
nehmen (DISTINCT, ORDER BY, LIMIT 1?), und- das Ergebnis dieser Auswahl dann wiederum nach dem Wert zu sortieren.
Ich weiß im Moment nicht, ob diese doppelte Sortierung mit einem einzigen
SELECT geht; es kann sein, daß dafür ein SubSelect erforderlich wäre, was
mySQL nicht direkt unterstützt.
In diesem Fall könntest Du aber den ersten SELECT in eine temporäre Tabelle
lenken und aus dieser mit dem zweiten die endgültige Sortierung heraus-
fischen.
So isses, habe nach langem verzweifelten Suchen bei mysql.com folgende Seite gefunden, die genau mein Ziel nochmal in einem Subselect zeigt und die MySQL-Lösung vorstellt, finde ich aber ziemlich umständlich im Gegensatz zum Subselect:
http://www.mysql.com/doc/e/x/example-Maximum-column-group-row.html
Trotzdem vielen Dank
Viele Grüße
Michael
Jo, auch von mir; Falls Du zum Ausgleich für Deine Bemühungen ein bisschen spielen willst: das Spiel liegt nicht (wie fälschlicherweise angegeben) unter schigold.de, sondern unter http://schigold.de/spiel/.
Hi Andreas,
finde ich aber ziemlich umständlich im Gegensatz zum Subselect:
das Beispiel wird m. E. deshalb so umständlich, weil es gleichzeitig
eine potentielle Transaktion am Leben halten will. Und das ist bei zwei
Statements nun mal nicht dasselbe wie bei nur einem im AutoCommit-Modus.
Im Prinzip siehst Du bei mySQL ja nur, wie jede Datenbank ein Subselect
intern realisieren muß - hier mußt Du es halt explizit hinschreiben.
(Potentiell könnte man SubSelects beliebig tief schachteln, und das
stellt dann so hohe Anforderungen an eine effiziente Verwaltung der
Ressourcen, daß sich mySQL dieser Herausforderung bisher anscheinend
nicht stellen möchte.)
Wenn Du nur lesend auf Deine Tabelle zugreifen willst und keine hohe
Prirität darauf legst, daß Dein Skript niemals inkonsistente Daten
im Falle gleichzeitiger Zugriffe anzeigt, könntest Du das LOCK und
das UNLOCK weglassen. Und auch das DROP brauchst Du bei einer tempo-
rären Tabelle nicht, wenn Du mal eben einen CGI-Zugriff machst - die
existiert nur während Deiner Datenbankverbindung.
Wäre Dein Programm als daemon dauerhaft mit der Datenbank verbinden,
dann wäre das sofortige, aktive Aufräumen der Tabelle wichtiger.
Das Beispiel zeigt Dir die "volle Dröhnung" unter Berücksichtigung
aller Eventualitäten. In Deinem Falle geht es wohl auch "billiger".
Viele Grüße
Michael