Pit: mysql: Rechnen mit mysql

Hallo,

ich habe 3 Tabellen und möchte etwas errechnen. Ich frage mich, ob ich das in einer Query hin bekommen kann, in mehreren Queries ist natürlich kein Problem.

Tabelle Namen enthält die Spalte Name Tabelle Spiele enthält alle Spiele, das Spieledatum wird in der Spalte Spieledatumals timestamp festgehalten. Tabelle Einsaetze enthält in der Spalte Namen kommasepariert die Namen der Spieler und in der Spalte SpieleID die ID des Spiels (wobei letzteres eher unwichtig für meine Frage ist). In der Spalte Einsatzdatum ist als timestamp das Datum/Zeit des Einsatzes enthalten.

Was ich gerne als Output hätte:

Für alle Spieler der Namenstabelle hätte ich gerne je (Kalender)jahr den prozentualen Einsatz zur Anzahl der Spiele in diesem Jahr. Hierbei ist egal, wie lange der Einsatz war, er muß nur in der Einsatztabelle verzeichnet sein. Jeder Spieler kann allerdings je Spiel mehrfach eingestzt werden, allerdings je Datensatz der Einsatztabelle nur ein mal.

Alternativ würde mir auch schon sehr weiterhelfen, wenn ich den Output (also die Jahresaufstellung) für einen ganz bestimmten Spieler hätte.

Geht das überhaupt in einer Query oder benötige ich auf jeden Fall mehrere Queries und php hierzu?

Pit

  1. Tach!

    Tabelle Spiele enthält alle Spiele, das Spieledatum wird in der Spalte Spieledatumals timestamp festgehalten.

    Timestamps (also Feldtyp TIMESTAMP) sind für das Festhalten des Erstellungs- oder Änderungszeitpunktes vorgesehen und bringen diesbezügliche Automatismen mit. Für anders geartete Zeiten sind DATE, TIME und DATETIME vorgesehen.

    Tabelle Einsaetze enthält in der Spalte Namen kommasepariert die Namen der Spieler

    Ganz schlechtes Datenbankdesign, besonders ...

    Für alle Spieler der Namenstabelle hätte ich gerne je (Kalender)jahr den prozentualen Einsatz zur Anzahl der Spiele in diesem Jahr.

    ... wenn nach Spielern Daten auszuwerten sind.

    Alternativ würde mir auch schon sehr weiterhelfen, wenn ich den Output (also die Jahresaufstellung) für einen ganz bestimmten Spieler hätte.

    Du kannst durch die Tabelle Namen gehen und nun für jeden Namen jeweils die gesamte Spiele-Tabelle durchlaufen und jeden Datensatz einzeln mit Stringoperationen malträtieren, um das Vorhandensein des Spielers zu ermitteln, aber schön und effizient geht anders.

    Geht das überhaupt in einer Query oder benötige ich auf jeden Fall mehrere Queries und php hierzu?

    Das geht schon, aber das will man keiner Datenbank zumuten, weil sie für solcherart Datenhaltung keine Optimierungsmechanismen (z.B. Index) heranziehen kann. Gleichartige Daten gehören nicht "nebeneinander" (kommasepariert oder Felder) sondern "untereinander" (je ein Datensatz).

    dedlfix.

    1. Hi dedlfix,

      Ganz schlechtes Datenbankdesign, besonders ...

      Ich weiß, ich weiß... würde ich natürlich heute ganz anders machen, aber vor xy Jahren wars halt so.

      Für alle Spieler der Namenstabelle hätte ich gerne je (Kalender)jahr den prozentualen Einsatz zur Anzahl der Spiele in diesem Jahr.

      ... wenn nach Spielern Daten auszuwerten sind.

      Was normalerweise nicht der Fall ist. Das Ganze ist eine kleine Auswertung für mich selber..

      Das geht schon, aber das will man keiner Datenbank zumuten, weil sie für solcherart Datenhaltung keine Optimierungsmechanismen (z.B. Index) heranziehen kann. Gleichartige Daten gehören nicht "nebeneinander" (kommasepariert oder Felder) sondern "untereinander" (je ein Datensatz).

      Dann also doch "zu Fuß" per php+mysql? Na ok, warum nicht, ich wollt ja nur wissen, obs auch einfacher bzw. effizienter geht. Wenn nicht, dann mach ichs zu fuß. Danke für die Anwort.

      Pit

      1. Tach!

        Dann also doch "zu Fuß" per php+mysql? Na ok, warum nicht, ich wollt ja nur wissen, obs auch einfacher bzw. effizienter geht. Wenn nicht, dann mach ichs zu fuß. Danke für die Anwort.

        Ob du die Lösung im DBMS oder außerhalb ansiedelst, macht das Kraut nicht mehr fett. Immerhin kannst du mit MySQL und der Funktion FIND_IN_SET() auch solche kommaseparierten Listen nach dem Vorhandensein von Werten befragen .

        Das Rechnen ist am Ende einfach, aber wie beschafft man sich die dafür notwendigen Zahlen? Nun, die Anzahl der Einsätze kannst du mit einer Correlated Subquery ermitteln. Die muss die Datensätze der Spiele-Tabelle zählen, in der FIND_IN_SET() für den jeweiligen Namen einen Treffer findet. Und wie immer bei Subquerys kann man diese auch erstmal abseits der Hauptquery erstellen, dann aber ohne Korrelation sondern in dem Fall mit einem beliebig ausgewählten Spielernamen. Das Ergebnis dieser Subquery muss dann eine einzelne Zahl liefern, die Anzahl der mitgespielten Spiele.

        Die zweite Zahl ist die Anzahl der Spiele insgesamt. Das könnte man auch in eine Subquery packen, aber da sich dieser Wert nicht ändert, ist es sinnvoll, ihn vorher in eine nutzerdefinierte Variable abzulegen und diese dann in der Query zu verwenden.

        dedlfix.

        1. Hi dedlfix,

          Ob du die Lösung im DBMS oder außerhalb ansiedelst, macht das Kraut nicht mehr fett. Immerhin kannst du mit MySQL und der Funktion FIND_IN_SET() auch solche kommaseparierten Listen nach dem Vorhandensein von Werten befragen .

          Ich hätte das jetzt mit %LIKE% gemacht. Ist FIND_IN_SET() besser?

          Die zweite Zahl ist die Anzahl der Spiele insgesamt. Das könnte man auch in eine Subquery packen, aber da sich dieser Wert nicht ändert, ist es sinnvoll, ihn vorher in eine nutzerdefinierte Variable abzulegen und diese dann in der Query zu verwenden.

          Doch, die Anzahl der Spiele ändert sich. Sie ist nichtmal in jedem jahr gleich.

          Pit

          1. Tach!

            Ich hätte das jetzt mit %LIKE% gemacht. Ist FIND_IN_SET() besser?

            Einfacher. Beim LIKE machen dir Namen am Anfang und Ende Probleme, weil da keine Kommas sind.

            Doch, die Anzahl der Spiele ändert sich. Sie ist nichtmal in jedem jahr gleich.

            Ja, aber die ändert sich nicht während die Abfrage läuft.

            dedlfix.

            1. ... wie bekomme ich eigentlich die Gruppierung nach Jahren hin?

              Pit

              1. Tach!

                ... wie bekomme ich eigentlich die Gruppierung nach Jahren hin?

                Die ergibt sich von selbst, wenn du die Spiele eines Spielers und eines Jahres zählst. COUNT() ist eine Aggregatfunktion, die fasst das Ergebnis zusammen.

                Du brauchst erstmal keine Gruppe sondern ein kartesisches Produkt aus Spieler und Jahr. Um allerdings alle Jahre zu ermitteln, die in der Datenbank sind, kannst du die Spiele-Tabelle befragen und da übers Jahr gruppieren.

                Wenn du die Aufgaben immer auf kleine eigenständige Teilaufgaben runterbrichst, kannst du eine Menge Dinge für die Gesamtlösung sehr einfach zusammentragen. Du brauchst die Namen aller Spieler? Dann erstell eine Query, die so eine Liste ergibt. Du brauchst eine List der Jahre, dann erstell eine weitere Query, um sie zu ermitteln. Du brauchst eine Kombination aus Spieler und Jahr, um dafür dann weitere Daten zu ermitteln? Bring die beiden vorherigen Querys zusammen. Wenn das Zwischenergebnis passt, mach weiter mit dem nächsten Teil.

                dedlfix.

                1. Hi dedlfix,

                  Die ergibt sich von selbst, wenn du die Spiele eines Spielers und eines Jahres zählst. COUNT() ist eine Aggregatfunktion, die fasst das Ergebnis zusammen.

                  Aber auch die hätte ich ja gerne übers Jahr gruppiert...

                  Ich dachte YEAR(Spalte), aber da kam Käse raus.

                  Pit

                  1. Tach!

                    Die ergibt sich von selbst, wenn du die Spiele eines Spielers und eines Jahres zählst. COUNT() ist eine Aggregatfunktion, die fasst das Ergebnis zusammen.

                    Aber auch die hätte ich ja gerne übers Jahr gruppiert...

                    Du brauchst an der Stelle keine Gruppierung, du möchtest da nur zählen.

                    WHERE YEAR(Spalte) = andere_tabelle.jahr AND Find_IN_SET(...

                    dedlfix.