Maik W. aus E.: mySQL: Count über mehrere Spalten

Tach zusammen,

möchte gerne eine Art Hitparade über die Anzahl bestimmter Werte in meiner Tabelle haben. Für eine Spalte klappt das auch sehr schön:

  
SELECT COUNT( b.arznei ) AS anzahl, b.arznei  
      FROM ueb_behandlungen b,  
      GROUP BY arznei  
      ORDER BY anzahl DESC  

Jetzt gibt es fünf Spalten, in denen Arzneiwerte stehen, und es ist (jetzt doch) nicht relevant, in welcher Spalte sie eingetragen sind.

Wie kann ich eine sortierte Ausgabe über die Häufigkeit eines Vorkommens eines Wertes über mehrere Spalten machen? Meine Versuche mit zwei "Count" in einer Abfrage trugen keine Früchte...

Oder muß ich das einzeln ziehen und in PHP zusammenzählen?

Danke und
http://www.gruss-aus-essen.de

Maik

  1. Hallo Maik,

    möchte gerne eine Art Hitparade über die Anzahl bestimmter Werte in meiner Tabelle haben. Für eine Spalte klappt das auch sehr schön:

    Jetzt gibt es fünf Spalten, in denen Arzneiwerte stehen, und es ist (jetzt doch) nicht relevant, in welcher Spalte sie eingetragen sind.

    Verstehe ich Dich richtig. Fünf Spalten enthalten prinzipiell vergleichbare Werte, aus welchem Grund auch immer. Diese möchtest Du nun zusammenfassen in einer Spalte. Grundsätzlich vermute ich mal wieder Fehler im Tabellen/Datenbankdesign. Das muss aber nicht so sein.

    Könntest Du dies bitte an einem Beispiel verdeutlichen? Beispieldaten und gewünschtes Ergebnis.

    Freundliche Grüße

    Vinzenz

    1. Tach auch Vinzenz,

      Jetzt gibt es fünf Spalten, in denen Arzneiwerte stehen, und es ist (jetzt doch) nicht relevant, in welcher Spalte sie eingetragen sind.

      Verstehe ich Dich richtig. Fünf Spalten enthalten prinzipiell vergleichbare Werte, aus welchem Grund auch immer. Diese möchtest Du nun zusammenfassen in einer Spalte.

      Im Grunde ja.

      Könntest Du dies bitte an einem Beispiel verdeutlichen? Beispieldaten und gewünschtes Ergebnis.

      Es gibt eine Tabelle mit Behandlungen, denen bis zu fünf eingesetzte Arzneien zugeordnet werden können:

      beh_id |arznei1|arznei2|arznei3|...
         1   |   78  |   12  |   0   |
         2   |   12  |   0   |   0   |

      Ursprünglich war die Anforderung, daß festgestellt werden kann, welches die Erstmedikation ist (arznei1), welches die Zweit- (arznei2), etc. Dies ist aber nicht mehr relevant, sondern eine Liste der Häufigkeit der der Arzneien insgesamt ist gesucht:

      anzahl |arznei
      ---------------
        3    |   0
        2    |  12
        1    |  78

      Bißchen klarer?

      http://www.gruss-aus-essen.de

      Maik

      1. Hallo!

        Es gibt eine Tabelle mit Behandlungen, denen bis zu fünf eingesetzte Arzneien zugeordnet werden können:

        beh_id |arznei1|arznei2|arznei3|...
           1   |   78  |   12  |   0   |
           2   |   12  |   0   |   0   |

        »»
        »»

        anzahl |arznei

        3    |   0
          2    |  12
          1    |  78

        Vielleicht ist es günstiger, deine Tabelle anders aufzubauen

        beh_id | arznei | grad
          1    |   78   |   1
          1    |   12   |   2
          2    |   12   |   1

        Damit sollte die Anfrage wieder entsprechend leicht zu beantworten sein.

        Viele Grüße
        nance

      2. Hallo Maik,

        Könntest Du dies bitte an einem Beispiel verdeutlichen? Beispieldaten und gewünschtes Ergebnis.
        Es gibt eine Tabelle mit Behandlungen, denen bis zu fünf eingesetzte Arzneien zugeordnet werden können:
        Ursprünglich war die Anforderung, daß festgestellt werden kann, welches die Erstmedikation ist (arznei1), welches die Zweit- (arznei2), etc.

        und leider zu einem ungünstigen DB-Design führte ...

        Dies ist aber nicht mehr relevant, sondern eine Liste der Häufigkeit der der Arzneien insgesamt ist gesucht:

        beh_id |arznei1|arznei2|arznei3|...
           1   |   78  |   12  |   0   |
           2   |   12  |   0   |   0   |

        anzahl |arznei

        3    |   0
          2    |  12
          1    |  78

        Bißchen klarer?

        Ja, mir ist eine Lösung mit Verwendung von UNION und Subselects eingefallen, diese beiden Features werden jedoch nicht von jeder MySQL-Version unterstützt. Welche MySQL-Version steht Dir zur Verfügung?

        Freundliche Grüße

        Vinzenz

        1. Hallo Maik,

          hier noch die SQL-Anweisung (hier für drei Arzneien, die Erweiterung an Deine Bedürfnisse sollte Dir nicht schwer fallen)

          beh_id |arznei1|arznei2|arznei3|...
             1   |   78  |   12  |   0   |
             2   |   12  |   0   |   0   |

            
          SELECT                         /* Die Zielspalten, klar */  
            count(b.arznei) AS Anzahl,   /* Anzahl                */  
            b.arznei                     /* Häufigkeit            */  
          FROM (  
            SELECT  
              id,                        /* aus welcher Zeile     */  
              a1 AS arznei,              /* gewünschte Daten      */  
              'a' AS spalte              /* aus welcher Spalte    */  
            FROM behandlungen  
            /* Anmerkungen:  
               Spaltennamen kannst Du nur in der ersten SELECT-Anweisung vorgeben  
               Eigentlich sollte ALL dafür sorgen, dass alle Datensätze angezeigt  
               werden, aber irgendwie wollten weder MySQL noch MS SQL Server 2000.  
               Daher habe ich zur Identifikation jeden Wertes mit Spalte und Zeile  
               gearbeitet.  
            */  
            UNION  
            SELECT id, a2, 'b' FROM behandlungen  
            UNION  
            SELECT id, a3, 'c' FROM behandlungen  
          ) AS b  
          GROUP BY b.arznei              /* Gruppierungsfeld       */  
          ORDER BY Anzahl DESC           /* Sortierung             */  
          
          

          anzahl |arznei

          3    |   0
            2    |  12
            1    |  78

          Ja, mir ist eine Lösung mit Verwendung von UNION und Subselects eingefallen, diese beiden Features werden jedoch nicht von jeder MySQL-Version unterstützt. Welche MySQL-Version steht Dir zur Verfügung?

          Mein Statement habe ich mit MySQL 4.1.11 getestet.
          Möglicherweise gibt es auch andere Möglichkeiten; dies war die erste, die mir eingefallen ist und erfreulicherweise trotz des defekten Tabellendesigns (siehe Posting von nance) zum gewünschten Resultat führt.

          Freundliche Grüße

          Vinzenz

          1. Tach auch Vinzenz,

            Vielen Dank für Deine Mühe!

            hier noch die SQL-Anweisung (hier für drei Arzneien, die Erweiterung an Deine Bedürfnisse sollte Dir nicht schwer fallen)

            Die sieht sehr gut aus, dummereweise kann ich nur auf mySQL Version 4.0.15 zurückgreifen, es wird also wie erwartet ein Fehler ausgegeben...

            Ja, mir ist eine Lösung mit Verwendung von UNION und Subselects eingefallen, diese beiden Features werden jedoch nicht von jeder MySQL-Version unterstützt. Welche MySQL-Version steht Dir zur Verfügung?

            Wie gesagt 4.0.15; noch 'ne Idee?

            http://www.gruss-aus-essen.de

            Maik

            1. Hallo Maik,

              Die sieht sehr gut aus, dummereweise kann ich nur auf mySQL Version 4.0.15 zurückgreifen, es wird also wie erwartet ein Fehler ausgegeben...

              Ja, das ist zu erwarten, aber so gut war die gar nicht. (Ich gehöre ins Bett :-( ). So ist es besser:

                
              SELECT                         /* Die Zielspalten, klar */  
                count(b.arznei) AS Anzahl,   /* Anzahl                */  
                b.arznei                     /* Häufigkeit            */  
              FROM (  
                SELECT a1 AS arznei FROM behandlungen  
                UNION ALL  
                SELECT a2 FROM behandlungen  
                UNION ALL  
                SELECT a3 FROM behandlungen  
              ) AS b  
              GROUP BY b.arznei              /* Gruppierungsfeld       */  
              ORDER BY Anzahl DESC           /* Sortierung             */  
              
              

              Wie gesagt 4.0.15; noch 'ne Idee?

              Das, was Dir hier jeder schon gesagt hat: Baue Deine Datenbank um, verwende eine sinnvolle Tabellenstruktur. Eine bessere Lösung gibt es nicht, selbst bei einer Version > 4.1 wäre obiges Statement ein Notbehelf aber keine echte Lösung.

              Eine Idee hätte ich, nicht besonders elegant:
               - Erstelle eine temporäre Tabelle mit der einen notwendigen Spalte
               - Kopiere die entsprechenden Datensätze in diese temporäre Tabelle
               - Führe Deine Abfrage auf die temporäre Tabelle aus
               - Lösche die temporäre Tabelle.

              Da dürfte die Auswertung in der API wahrscheinlich geringeren Aufwand bedeuten. Bei Dir kommen unzulängliches DB-Design und unzulängliches DBMS zusammen. Ersteres könntest Du eventuell ändern, auf das zweite dürfte Dein Einfluss geringer sein.

              Freundliche Grüße

              Vinzenz

              1. Tach auch Vinzenz,

                Da dürfte die Auswertung in der API wahrscheinlich geringeren Aufwand bedeuten. Bei Dir kommen unzulängliches DB-Design und unzulängliches DBMS zusammen. Ersteres könntest Du eventuell ändern, auf das zweite dürfte Dein Einfluss geringer sein.

                So sieht es aus... Da werde ich mich wohl an eine API-seitige Lösung machen...

                Dank Dir trotzdem

                http://www.gruss-aus-essen.de

                Maik

      3. Hi!

        Ursprünglich war die Anforderung, daß festgestellt werden kann, welches die Erstmedikation ist (arznei1), welches die Zweit- (arznei2), etc. Dies ist aber nicht mehr relevant,

        Bis du noch in der Entwicklungsphase? Wenn ja, rate ich dir dringend das Design anzupassen.
        Wenn du nun schon anfängst "Notlösungen" zu basteln wirst du auf dauer nicht glücklich. Klar, das bedeutet vielleicht Überstunden aber irgendwann macht sich das bezahlt. Wenn sich Anforderungen ändern, musst du halt in den Sauren Apfel beißen. Letztendlich bist du verantwortlich das alles performant und konsistent arbeitet. Vielleicht hast du anfangs ein Pflichtenheft unterschreiben lassen, dann kannst du ja deinem Auftraggeber Änderungen der Anforderungen in Rechnung stellen.

        Was spricht also gegen:
        Tabelle: Behandlungen
        Tabelle: Arznei
        Relationstabelle: Behandlung-Arznei

        Gruß