Yadgar: Prozentwerte aus gruppierten Werten errechnen

High!

Ich bin jetzt ein Stück weiter vorangekommen mit meiner Elektronikorgel-Datenbank (das Problem mit den bedingten Feldern für meistens nicht vorhandene Dritt- und Viertmanuale habe ich "konventionell" gelöst, also mit eventuell leer bleibenden Feldern), die ersten 20 Modelle sind schon eingetragen, jetzt würde ich gerne die Anteile der einzelnen Marken an der Gesamtzahl errechnen.

"Marke" ist ein Feld in der Tabelle "orgeln" und verweist auf die Tabelle "marken", wo unter "Markenname" der Markenname im Klartext steht.

Das bloße Anzeigen der Häufigkeiten der einzelnen Marken war kein Problem:

select marken.Markenname, count(orgeln.Modell) as Anzahl_Modelle from orgeln, marken where orgeln.Marke=marken.Nr group by Markenname;

Aber wie bekomme ich die Gesamtzahl der Orgelmodelle ermittelt, wenn am Ende der Abfrage zwangsläufig GROUP BY stehen muss? Zweistufig, über die vorherige Definition einer Variable @gesamtzahl ist es machbar, aber sonderlich elegant kommt mir das nicht vor. Gibt es eine Möglichkeit, dasselbe Ergebnis mit nur einer Abfrage zu erreichen?

Bis bald im Khyberspace!

Yadgar

  1. Hallo,

    kannst du in deiner MySQL Version "Views" definieren? Oder funktionieren Unterabfragen (Subqueries) oder kannst du Stored Procedures schreiben? Erstmal rein von der Unterstützung durch das Datenbanksystem?

    Mit Views könntest du dir die jeweiligen Views, einmal Totalcount und einmal Count pro Markenname zurechtbasteln und dann zusammenfügen.

    Wenn Subqueries unterstütztwerden, kannst du z.b./evt. sowas machen

    SELECT Marke,
           COUNT(*) AS CountByMarke,
           (SELECT COUNT(*) FROM Orgeln) AS TotalCount,
           (CountByMarke / TotalCount) AS Anteil
       FROM Orgeln
       GROUPY BY Marke

    In Stored Procedures könntest du hingegen zuerst eine Variable setzen mit dem Totalcount und dann in der eigentlichen Abfrage wiederwenden?

    Kann MySQL eigentlich auch mit ganzen Batches umgehen, also quasi ...

    DECLARE @var1 int;
    SELECT @var1 = COUNT(*) FROM Orgeln;
    SELECT Marke,
           COUNT(*) AS CountByMarke,
           @var1,
           (CountByMarke / @var1) AS Anteil
       FROM Orgeln
       GROUPY BY Marke;

    ... in einem Aufruf?

    Das Bedürfnis nach "Eleganz" muss man manchmal je nach Unterstützung durch die Software etwas hin anstellen. Ausserdem kommt es imho bei Softwareentwicklung nicht wirklich auf Eleganz an, beim Ballett schon eher. :)

    Ciao, Frank

    1. High!

      Wenn Subqueries unterstütztwerden, kannst du z.b./evt. sowas machen

      SELECT Marke,
             COUNT(*) AS CountByMarke,
             (SELECT COUNT(*) FROM Orgeln) AS TotalCount,
             (CountByMarke / TotalCount) AS Anteil
         FROM Orgeln
         GROUPY BY Marke

      Subqueries werden unterstützt, also versuchte ich es mal mit

      select marken.Markenname, count(orgeln.Modell) as Anzahl_Modelle, (count(orgeln.Modell)/(select count(*) from orgeln))*100 as Prozentanteil from orgeln, marken where orgeln.Marke=marken.Nr group by Markenname;

      dabei kamen allerdings merkwürdige Prozentwerte raus, nämlich:

      +-----------------+----------------+---------------+
      | Markenname      | Anzahl_Modelle | Prozentanteil |
      +-----------------+----------------+---------------+
      | Ahlborn         |              3 |       10.3448 |
      | Allen           |              2 |        6.8966 |
      | Baldwin         |              2 |        6.8966 |
      | Baleani         |              2 |        6.8966 |
      | Belton          |              2 |        6.8966 |
      | Bontempi        |              1 |        3.4483 |
      | Compton         |              1 |        3.4483 |
      | Conn            |              3 |       10.3448 |
      | CRB elettronica |              1 |        3.4483 |
      | Crumar          |              3 |       10.3448 |
      +-----------------+----------------+---------------+

      ...offenkundig Unsinn, da die Gesamtzahl der Orgeln 20 ist, sich also glatte Fünferzahlen ergeben müssten! Immerhin passen die Zahlen proportional zueinander, so dass der Fehler entweder beim Divisor oder dem Dividenden liegen muss...

      In Stored Procedures könntest du hingegen zuerst eine Variable setzen mit dem Totalcount und dann in der eigentlichen Abfrage wiederwenden?

      Kann MySQL eigentlich auch mit ganzen Batches umgehen, also quasi ...

      DECLARE @var1 int;
      SELECT @var1 = COUNT(*) FROM Orgeln;
      SELECT Marke,
             COUNT(*) AS CountByMarke,
             @var1,
             (CountByMarke / @var1) AS Anteil
         FROM Orgeln
         GROUPY BY Marke;

      ... in einem Aufruf?

      Batches funktionieren! Allerdings soll das Ganze irgendwann einmal webgängig mit einer noch zu programmierenden PHP/HTML-Benutzeroberfläche funktionieren...

      Das Bedürfnis nach "Eleganz" muss man manchmal je nach Unterstützung durch die Software etwas hin anstellen. Ausserdem kommt es imho bei Softwareentwicklung nicht wirklich auf Eleganz an, beim Ballett schon eher. :)

      Wie gesagt, für den MySQL-unerfahrenen Endbenutzer wäre es nicht so praktisch, wenn er vor der eigentlichen Ergebnistabelle noch ein Hilfstabellchen mit dem Summenwert zu sehen bekäme - so etwas irritiert doch!

      Bis bald im Khyberspace!

      Yadgar

      P.S. Gibt es eigentlich hier eigentlich eine Möglichkeit, Text in Blockschrift zu formatieren? Wäre praktisch, da ich MySQL gegenwärtig auf der Linux-Konsole fahre...

      1. Hallo ...

        "Batches" zu benutzen ist unter gewissen Umständen ein durchaus sinnvolle Gangart, besonders, wenn es die einfachste (pragmatischste) Art ist, ein Problem zu lösen. Und es gibt keinen wirklichen mir bekannten Grund, der dagegen spricht. Mit "webgängig" hat das imho nix zu tun. Du versteckst ja den SQL Code sowieso in den jeweiligen PHP Codeblöcken oder gar Klassen und Funktionen.

        MySQL-unerfahrenen Endbenutzer

        Werden solche Individuen dein "Programm" benutzen? Und selbst wenn, warum sollten sie was von Hilfsvariablen und -tabellen mitbekommen?

        Deine Abfrage bringt indertat etwas falsche Ergebnisse. Woran das jetzt genau liegt, kann ich dir ad-hoc mangels Kenntnis von MySQL nicht wirklich sagen. Aber wie sieht es aus, wenn du das ganze als Batch laufen lässt und erstmal die Gesamtzahl als Variable zwishcenspeicherst?

        Zur Not kann man ja auch 2 Abfragen auf die DB machen ... jaja, nicht besonders elegant, aber löst erstmal das Problem, oder?

        Cheers, Frank