Julia: Komplizierte MySQL-Abfrage!?

Hallo MySQL-Profis,

ich stehe hier vor einem Problem. Ich soll für eine Spendenorganisation eine Art Highscore-Liste für Spenden erstellen.

Die einzige Tabelle aus der die Daten kommen sieht folgendermaßen aus:

aktion  | name  |  spende  | datum  |
---------------------------------------
flut    | anton |      10  |2004-12-29
flut    | berta |      15  |2004-12-30
flut    | cäsar |       5  |2005-01-15
erdbeben| anton |       5  |2005-01-20
erdbeben| berta |      25  |2005-01-21
erdbeben| cäsar |       5  |2005-01-22
.
.
.

Die Ausgabe soll später so aussehen:

name | flut | erdbeben | gesamt
-------------------------------
berta|  15  |     25   |   40
anton|  10  |      5   |   15
cäsar|   5  |      5   |   10
.
.
.

Die Sortierung erfolgt also nach der Gesamtspendensumme des Spenders.

Lässt sich das durch eine MySQL-Abfrage abbilden? Wenn ja, hat jemand ein paar Ansätze die mir weiterhelfen könnten. Ich weiß ehrlich gesagt nicht wie ich das anfangen soll.

MySQL Version 4.0.18/PHP 4.2.2

Ich bin für jede Hilfe Dankbar!

Schöne Grüße
Julia

  1. Halihallo Julia

    name | flut | erdbeben | gesamt

    berta|  15  |     25   |   40
    anton|  10  |      5   |   15
    cäsar|   5  |      5   |   10
    Die Sortierung erfolgt also nach der Gesamtspendensumme des Spenders.

    Lässt sich das durch eine MySQL-Abfrage abbilden? Wenn ja, hat jemand ein paar Ansätze die mir weiterhelfen könnten. Ich weiß ehrlich gesagt nicht wie ich das anfangen soll.

    Generell und allgemein gesagt Nein. MySQL bzw. SQL unterstützt kein
    Abbilden von Attributwerten in Attributnamen (flug und erdbeben sind
    ja Attributwerte und sollen in der Ausgabe *plötzlich* zu
    Attributnamen verwandelt werden, das ist böse Magie!).

    Speziell aber ja. Speziell genau dann, wenn du eine fixe Anzahl an
    Katastrophen hast (im Beispiel 2) bzw. eine Technik wie PHP was dir
    ja zur Verfügung steht, mit Hilfe dieser du die Anfrage dynamisch
    zusammenstellen kannst.

    Dann geht's sinngemäss über korrelierte Subqueries so:

    SELECT
       a.name,
       (
          SELECT SUM(spende) FROM table WHERE name=a.name
             WHERE aktion='flut'
       ) AS 'flut',
       (
          SELECT SUM(spende) FROM table WHERE name=a.name
             WHERE aktion='erdbeben'
       ) AS 'erdbeben',
       (
          SELECT SUM(spende) FROM table WHERE name=a.name
       ) AS 'gesamt'
    FROM table AS a
    GROUP BY a.name
    ORDER BY gesamt

    Nun, jeder Datenbankexperte würde dich für dieses Konstrukt zwar
    umbringen und die meisten Datenbanken quittieren dir den Dienst mit
    einer Fehlermeldung, aber ich könnte mir doch vorstellen, dass MySQL
    da mitmacht.

    Oftmals werden Subqueries in der SELECT-Klausel ganz verweigert.
    Andere Datenbanken (z.B. DB2) lassen einwertige und einattributige
    Subqueries in SELECT zu.

    Zudem sind diese korrelierten Subqueries, wenn es eine schnellere
    Lösung gibt, zu unterlassen (was für eine Erkenntnis :-)).

    Eine andere, aber ebenso stupide Lösung wäre über drei Joins zu
    gehen. Ggf. mit der Prämisse, dass jeder mindestens einmal für jede
    Katastrophe spendet, dann gehts sogar ohne grössere Tricks
    (unbestätigt aber etwas bedacht in den Raum geworfen).

    Nun, zusammenfassend: Über eine SQL-Anfrage würde ich dies kaum
    machen, besonders nicht weil du PHP als Vorhanden zeichnest. Überlege
    dir, wie du mit PHP und zwei SQL-Anfragen an dein Ziel kommst.

    Viele Grüsse

    Philipp

    1. Hallo

      nur als Ergänzung zu Philipps Ausführungen:

      name | flut | erdbeben | gesamt

      berta|  15  |     25   |   40
      anton|  10  |      5   |   15
      cäsar|   5  |      5   |   10

      Generell und allgemein gesagt Nein. MySQL bzw. SQL unterstützt kein
      Abbilden von Attributwerten in Attributnamen (flug und erdbeben sind
      ja Attributwerte und sollen in der Ausgabe *plötzlich* zu
      Attributnamen verwandelt werden, das ist böse Magie!).

      Jet-SQL, d.h. der SQL-Dialekt, den die Jet-Database-Engine, die v.a. hinter Microsoft Access steckt, unterstützt diese Anforderung. Das nennt sich in Access Kreuztabellenabfrage.

      Syntax:

      TRANSFORM Aggregatfunktion
      SELECT-Anweisung
      PIVOT PivotFeld [IN (Wert1[, Wert2[, ...]])]

      Freundliche Grüße

      Vinzenz

    2. yo,

      ja Attributwerte und sollen in der Ausgabe *plötzlich* zu
      Attributnamen verwandelt werden, das ist böse Magie!).

      oder PL/SQL....

      »» Zudem sind diese korrelierten Subqueries, wenn es eine schnellere

      Lösung gibt, zu unterlassen (was für eine Erkenntnis :-)).

      eventuell sollte es auch über GROUP BY aktion, name gehen und zusätzlich über Control Flow Functions wie IF, die den inhalt von aktion überprüft und entsprechend verzweigt. damit sollten sich die unterabfragen vermeiden lassen (ohne prügunf nur eine fixe idee). aber auch hierzu muss man die namen der einzelnen katastrophen kennen und somit die anzahl.

      Ilja

      1. Halihallo Ilja

        Zudem sind diese korrelierten Subqueries, wenn es eine schnellere
        Lösung gibt, zu unterlassen (was für eine Erkenntnis :-)).

        eventuell sollte es auch über GROUP BY aktion, name gehen und zusätzlich über Control Flow Functions wie IF, die den inhalt von aktion überprüft und entsprechend verzweigt. damit sollten sich die unterabfragen vermeiden lassen (ohne prügunf nur eine fixe idee). aber auch hierzu muss man die namen der einzelnen katastrophen kennen und somit die anzahl.

        Ich glaube, dass käme auf meine Drei-Join-Aufgabe heraus, denn
        andernfalls bringt dir IF wenig, da es nach dem GROUP BY
        Interpretiert wird. Die Daten befänden sich bereits im aggregierten
        Zustand und wären für IF unverwertbar.

        Viele Grüsse

        Philipp

        1. yo,

          Ich glaube, dass käme auf meine Drei-Join-Aufgabe heraus, denn
          andernfalls bringt dir IF wenig, da es nach dem GROUP BY
          Interpretiert wird. Die Daten befänden sich bereits im aggregierten

          sicherlich war bei mir eine spalte im group by zuviel, aber es sollte meiner meinung nach ohne joins und subquerys so gehen.

          SELECT name, SUM(IF(aktion="flut", spende, 0)) As Flut, SUM(IF(aktion="erdbeben", spende, 0)) AS Erdbeben, SUM(spende) AS Gesamt
          FROM gruppe
          GROUP BY name
          ORDER BY 4 DESC

          Ilja

          1. Halihallo Ilja

            SELECT name, SUM(IF(aktion="flut", spende, 0)) As Flut, SUM(IF(aktion="erdbeben", spende, 0)) AS Erdbeben, SUM(spende) AS Gesamt
            FROM gruppe
            GROUP BY name
            ORDER BY 4 DESC

            Du hast recht. Ich dachte, dass hier IF nicht geht, da es sich auf
            ein aggregiertes Attribut bezieht. Es funktioniert jedoch, wie ich
            eben versucht habe. Ist ja eigentlich auch logisch, wie so vieles im
            Nachhinein :-)

            Schöne Ostern und Dank der Korrektur

            Philipp

            1. yo,

              Schöne Ostern und Dank der Korrektur

              nun, jedesmal wenn wir vorher miteinander diskutiert haben, war es sehr lehrreich für mich. ich denke mal, sehr bald werde ich wieder die oster-hasen-ohren aufsperren...

              prost und frohe ostern

              Ilja

              1. Halihallo Ilja

                Schöne Ostern und Dank der Korrektur

                nun, jedesmal wenn wir vorher miteinander diskutiert haben, war es sehr lehrreich für mich.

                Vielen Dank, es war mir stets eine herausfordernde Freude :-)

                prost und frohe ostern

                YYYYYYYYYYYYYY und gleichfalls.

                Viele Grüsse

                Philipp