Okay, also dieses "LOCK TABLES" scheint das zu sein, was ich brauche. Allerdings habe ich bei der Hälfte der Erklärung nur Bahnhof verstanden, weil ich auch in sachen SQL eigentlich keine Ahnung habe... Ich denke, ich könnte bei dieser Uptdate-Geschichte ein bisschen Hilfe gebrauchen...
Ich erkläre das Problem noch mal ein bisschen genauer:
Es geht um einen Bot, der im Warcraft 3 - Battle.net Spiele hostet und am Ende jedes Spiel die Datenbank aktualisiert. Das umfasst im wesentlichen vier Tabellen:
games - ein neuer Eintrag
dotagames - ein neuer Eintrag, wenn das Spiel ein Dotaspiel war (in der Regel immer)
gameplayers - soviele neue Einträge, wie Spieler im Spiel waren
dotaplayers - 10 neue Einträge, wenn das Spiel ein Dotaspiel war (in der Regel immer)
Jeder Eintrag in jeder Tabelle hat natürlich eine fortlaufende Id zur eindeutigen Identifizierung. Jede der Tabellen mit Ausnahme der Tabelle "games" besitzt eine Spalte "gameid", in der die Id des zugehörigen Eintrags in der games-Tabelle steht.
In der Tabelle "dotaplayers" gibt es eine Spalte "colour". Sie beinhaltet die Farbe des Spielers in Form einer Zahl von 1 bis 11 ohne 6. Da nach jedem Spiel 10 Spieler hinzugefügt werden, gibt es für alle Einträge mit der gleichen "gameid" jede Farbe genau einmal.
In der Tabelle "gameplayers" gibt es diese Spalte "colour" ebenfalls. Hat ein Eintrag aus der Tabelle "gameplayers" die gleiche "gameid" und "colour", wie ein Eintrag aus der Tabelle "dotaplayers", dann handelt es sich um den selben Spieler in dem selben Spiel. Weil allerdings nicht jedes Spiel ein Dotaspiel ist (könnte ja mal passieren) und nicht jedes Dotaspiel mit 10 Spielern gespielt wird (es gibt also Dummyeinträge), gibt es nicht für jeden "gameplayer" einen "dotaplayer" und andersrum ebenfalls.
Nun ist es außerdem so, dass der Name, der zur Identifikation des Spielers dient, NUR in der "gameplayers"-Tabelle in der Spalte "name" vorhanden ist. Er ist übrigens auch das einzige Feld, das ich von dieser Tabelle brauche, da die übrigen Statistiken für diese "Update-Geschichte" irrelevant sind.
In der Tabelle "dotagames" sind drei Spalten wichtig. Die erste nennt sich "winner". Ist der Wert eines Eintrags hier 0, so wurde das Spiel nicht beendet und es gibt keine auswertbaren Statistiken. Ist der Wert 1 oder 2, so hat "Sentinel" oder "Scourge" gewonnen. Die Spalten "min" und "sec" beinhalten die Spieldauer in Minuten und Sekunden.
Um zur Sache zu kommen:
Ich möchte eine neue Tabelle erstellen, in der für jeden Spieler aus der "dotaplayers"-Tabelle, der mindestens ein Dotaspiel beendet hat (winner != 0), eine Zeile vorhanden ist. In dieser Zeile sollen einige Statistiken aus den Einträgen der beendeten Spiele in der "dotaplayers"-Tabelle summiert stehen. Außerdem sollen dort die Anzahl der Spiele, die Anzahl der Siege und die gesammte Spielzeit des Spielers stehen.
Beispiel:
Ein Spieler mit dem Nicknamen hans hat insgesammt 2 Dotapiele beendet, eins mit der Dauer 40:30, das andere mit der Dauer 29:30, 1 Spiel davon hat er gewonnen. Betrachte ich nur die Spalte "kills" in "dotaplayers" (es gibt noch mehr): Im ersten Spiel hat er 10 Kills bekommen, im zweiten 12.
Der eintrag in der neuen Tabelle sieht also wie folgt aus:
name: hans
games: 2
wins: 1
playtime: 4200 (in Sekunden)
kills: 22
...
Außerdem sollen in die Tabellen noch ein paar Spalten eingetragen werden, die sich aus der Tabelle selbst ergeben, nämlich "winratio" (in diesem Fall 0.5), für alle Statistiken wie "kills" noch eine "-ratio" nach der Formel "kills / playtime * avaragegametime", wobei avaragegametime die durchschnittliche Dauer eines Dotaspiels ist, und noch eine Spalte, die ich "strength" getauft habe und für die ich mir eine komplexere Formel überlegt habe, die von "winratio", "games" und allen ratio-Statistiken wie "killratio" abhängt.
So weit, so gut, aber wie realisiere ich das?
Jedes mal, wen sich jemand eine Seite anschaut, die auf dieser Tabelle aufbaut, soll ein Query aufgerufen werden, der die Tabelle aktualisiert und nach einer gewissen Sortierung ausliest. Damit nicht jedesmal jedes Spiel und jeder Spieler ausgelesen wird, möchte ich die bereits gelesenen Spiele markieren, indem ich in der Tabelle "dotagames" eine neue Spalte "read" erstelle, die wahr oder falsch sein kann.
Im diesem Query müssen zunächsteinmal die beiden Tabellen irgendwie verriegelt werden (irgendwie LOCK TABLES), damit doppelte Aufrufe des Skripts sich nicht in die Quere kommen. Dann werden aus allen vier Tabellen passende 4-Tupel an Einträgen ausgewählt:
SELECT * FROM ´dotaplayers´, ´gameplayers´, ´dotagames´, ´games´ WHERE ´games´.´id´ = ´dotagames´.´gameid´ AND ´games´.´id´ = ´gameplayers´.´gameid´ AND ´games´.´id´ = ´dotaplayers´.´gameid´ AND ´dotagames´.´winner´ != 0 AND ´dotagames´.´read´ = FALSE
Habe ich das soweit richtig? Vorallem bei dem "!=" und dem "FALSE" bin ich mir nicht wirklich sicher...
Jetzt muss ich alle obengenannten Daten unter dem entsprechenden Eintrag (Schlüssel "name") in der neuen Tabelle aktualiseren und ab jetzt habe ich keine Ahnung mehr, denke ich. Was ist zum Beispiel, wenn der Eintrag noch nicht existiert, und wie addiere ich etwas zu einem Feld wie "kills".
Für die zusätzlichen Spalten wie "killratio" brauche ich auch noch die durchschnittliche Spieldauer, die ich aus allen Einträgen der "dotagames"-Tabelle errechnen könnte, aber wie Speichere ich mir soetwas?
Abschließend muss ich dann noch alle Werte der Spalte "read" der gelesenen Einträge auf true setzen und die Tabellen entriegeln.
In der Hoffnung, dass irgendjemand, der Ahnung von MySQL hat, bis zum Ende gelesen hat und sich für mein Problem interessiert
Speedy Consoles