Naggi: Befehl distinct() in Kombination mit count

Hallo *,

ich versuche derzeit, Ereignisse anhand einer Spielerid zu gruppieren und zusammenzuzählen, um die Anzahl der Spiele, Einwechslungen, Auswechslungen, Tore, Vorlagen etc. auszulesen.

Folgende Funktion hatte ich dafür angedacht, ausgelesen wird jedoch leider nichts:

// Start Code
$ereignisse= $db_zugriff->query("SELECT count(distinct(ereignis)) FROM lm_spielereignisse WHERE spieler_id='$id' GROUP BY ereignis");
while($spi = $db_zugriff->fetch_array($ereignisse)){
$start = $spi[ereignis];
}

echo "Anzahl Spiele:".$start;
// Ende Code

Woran mag dies liegen?

Danke & Gruß
Naggi

  1. Hi Naggi,

    Folgende Funktion hatte ich dafür angedacht, ausgelesen wird jedoch leider nichts:

    um Fehler besser zu erkennen lohnt es sich an diese Funktionen ein "or die(mysql_error())" anzuhängen, dann wird dir der Datenbankfehler ausgegeben.

    // Start Code
    $ereignisse= $db_zugriff->query("SELECT count(distinct(ereignis)) FROM lm_spielereignisse WHERE spieler_id='$id' GROUP BY ereignis");

    Ich kenne distinct nicht als Funktion, d.h. nicht, dass es sie nicht gibt. Ich würde distinct als Schlüsselwort verwenden direkt nach dem select.

    Viele gute Hinweise bekommst du auf mysql.de

    ciao
    romy

  2. Hell-O!

    $ereignisse= $db_zugriff->query("SELECT count(distinct(ereignis)) FROM lm_spielereignisse WHERE spieler_id='$id' GROUP BY ereignis");

    Mache dir klar, was das Statement ausliest, nämlich die Anzahl der unterschiedlichen Ereignisse, die in deiner DB vorkommen. Dein "GROUP BY" ist wirkungslos, da du die Spalte, nach der gruppiert werden soll, nicht selektierst, sondern zählst. Das Resultat deiner Abfrage (sofern kein Fehler geworfen wird) ist genau ein Datensatz (den Wert habe ich mal angenommen):

    count(distinct(ereignis))  
    -------------------------  
    25
    

    $start = $spi[ereignis];

    Es gibt in deinem Resultset keine Spalte mit Namen "ereignis", die du abfragen kannst (siehe die oben stehende Tabelle). Denkbar wäre eventuell sowas:

    SELECT  
      COUNT(DISTINCT(ereignis)) AS anzahl,  
      ereignis  
    FROM  
      tabellenname  
    WHERE  
      spieler_id = '$id'  
    GROUP BY  
      ereignis
    

    Dies sollte dir folgende Ergebnistabelle liefern:

    anzahl | ereignis  
    -----------------  
    1      | Rote Karte  
    3      | Gelbe Karte  
    6      | Tore
    

    Die Inhalte der Ergebnistabelle kannst du dann wie gewohnt abfragen.

    Siechfred

    1. Hell-O!

      $ereignisse= $db_zugriff->query("SELECT count(distinct(ereignis)) FROM lm_spielereignisse WHERE spieler_id='$id' GROUP BY ereignis");

      Mache dir klar, was das Statement ausliest, nämlich die Anzahl der unterschiedlichen Ereignisse, die in deiner DB vorkommen. Dein "GROUP BY" ist wirkungslos, da du die Spalte, nach der gruppiert werden soll, nicht selektierst, sondern zählst. Das Resultat deiner Abfrage (sofern kein Fehler geworfen wird) ist genau ein Datensatz (den Wert habe ich mal angenommen):

      count(distinct(ereignis))


      25

      
      >   
      > > $start = $spi[ereignis];  
      >   
      > Es gibt in deinem Resultset keine Spalte mit Namen "ereignis", die du abfragen kannst (siehe die oben stehende Tabelle). Denkbar wäre eventuell sowas:  
      >   
      > ~~~sql
      
      SELECT  
      
      >   COUNT(DISTINCT(ereignis)) AS anzahl,  
      >   ereignis  
      > FROM  
      >   tabellenname  
      > WHERE  
      >   spieler_id = '$id'  
      > GROUP BY  
      >   ereignis
      
      

      Dies sollte dir folgende Ergebnistabelle liefern:

      anzahl | ereignis


      1      | Rote Karte
      3      | Gelbe Karte
      6      | Tore

      
      >   
      > Die Inhalte der Ergebnistabelle kannst du dann wie gewohnt abfragen.  
      >   
      > Siechfred  
        
      Hallo Siechfried,  
        
      erst einmal vielen Dank für Deine Hilfe, die mich definitiv schon weiter gebracht hat.  
        
      Ein Problem besteht jedoch noch: Nachdem ich den von Dir erzeugten Code in PHPmyAdmin eingab, um zu testen, ob wirklich diese Ergebnistabelle ausgespuckt werden würde, war dies nur teils zufriedenstellen:  
        
      ~~~resultset
      anzahl | ereignis  
      -----------------  
      1      | 1  
      1      | 3  
      1      | 12
      

      Jedes Ereignis wird also nur einmal gezählt, obwohl das Ereignis 1 (Startaufstellung) allein 20 Mal vorkommt. Woran mag dies liegen? Stoppt die Abfrage nach einem Durchlauf?

      1. Moin!

        anzahl | ereignis


        1      | 1
        1      | 3
        1      | 12

        
        >   
        > Jedes Ereignis wird also nur einmal gezählt, obwohl das Ereignis 1 (Startaufstellung) allein 20 Mal vorkommt. Woran mag dies liegen? Stoppt die Abfrage nach einem Durchlauf?  
          
        Du hast count(distinct()) benutzt - was erwartest du da anderes? DISTINCT eliminiert Duplikate.  
          
         - Sven Rautenberg
        
        -- 
        My sssignature, my preciousssss!
        
        1. Moin!

          anzahl | ereignis


          1      | 1
          1      | 3
          1      | 12

          
          > >   
          > > Jedes Ereignis wird also nur einmal gezählt, obwohl das Ereignis 1 (Startaufstellung) allein 20 Mal vorkommt. Woran mag dies liegen? Stoppt die Abfrage nach einem Durchlauf?  
          >   
          > Du hast count(distinct()) benutzt - was erwartest du da anderes? DISTINCT eliminiert Duplikate.  
          >   
          >  - Sven Rautenberg  
            
          Wieso hab ich den denn bloß dringehabt? Steinigung erlaubt :)  
            
          Letzte Anfängerfrage (habe mich durch meinen inkompetenten Einbau ja eindeutig disqualifiziert \*g):  
            
          Wie lese ich nun die einzelnen Ereignisse aus?
          
          1. Wie lese ich nun die einzelnen Ereignisse aus?

            So, wie du es ursprünglich gemacht hast, die Namen der Indizes sind die Spaltennamen deines Resultsets (also "anzahl" und "ereignis"). Möchtest du zusätzlich statt der Ereignisnummer den Namen des Ereignisses haben, der möglicherweise in einer anderen Tabelle steht, dann beschäftige dich mit JOINs.

            Siechfred

            1. Moin!

              Wie lese ich nun die einzelnen Ereignisse aus?

              So, wie du es ursprünglich gemacht hast, die Namen der Indizes sind die Spaltennamen deines Resultsets (also "anzahl" und "ereignis"). Möchtest du zusätzlich statt der Ereignisnummer den Namen des Ereignisses haben, der möglicherweise in einer anderen Tabelle steht, dann beschäftige dich mit JOINs.

              GROUP BY verträgt sich mit JOIN nicht, jedenfalls nicht in der Hinsicht, dass man sowohl Gruppierungsergebnisse (hier: Anzahl ermitteln) und Einzelergebnisse (die gezählt wurden) in einer Abfrage erhält.

              Subselects sind sehr wahrscheinlich notwendig.

              - Sven Rautenberg

              --
              My sssignature, my preciousssss!
              1. Hell-O!

                GROUP BY verträgt sich mit JOIN nicht, jedenfalls nicht in der Hinsicht, dass man sowohl Gruppierungsergebnisse (hier: Anzahl ermitteln) und Einzelergebnisse (die gezählt wurden) in einer Abfrage erhält.

                Ah, danke für den Hinweis. Gibt's da was zum Nachlesen (außer auf dev.mysql.com, die Dokumentation ist in solchen Detailfragen m.E. eher dürftig).

                Siechfred

                1. Moin!

                  GROUP BY verträgt sich mit JOIN nicht, jedenfalls nicht in der Hinsicht, dass man sowohl Gruppierungsergebnisse (hier: Anzahl ermitteln) und Einzelergebnisse (die gezählt wurden) in einer Abfrage erhält.

                  Ah, danke für den Hinweis. Gibt's da was zum Nachlesen (außer auf dev.mysql.com, die Dokumentation ist in solchen Detailfragen m.E. eher dürftig).

                  Das kann sich auch nicht aus der Doku ergeben, sondern aus dem logischen Sinnzusammenhang von SQL-Abfragen.

                  GROUP BY vereinigt mehrere Tabellenzellen einer (möglicherweise durch JOIN aus diversen Tabellen erzeugten) Ergebnistabelle - soll heißen: Ohne GROUP BY entstünde eine Tabelle, in der einige Datensätze irgendwie zusammengefaßt werden sollen. Dabei werden Spalten, die identischen Inhalt haben, oft zum Gruppieren verwenden, und die Spalten mit unterschiedlichen Inhalten werden über eine der Aggregatfunktionen verfügbar gemacht. Die Einzelinhalte der jeweiligen Datensätze gehen dabei verloren.

                  Man kann aber eine gruppierte Tabelle nicht wieder auf die Ausgangstabelle joinen, weil GROUP BY erst nach dem JOIN wirksam wird. Man müßte sich das Ergebnis von GROUP BY also abspeichern, wieder einlesen, und darauf dann JOIN anwenden. Und genau das ist ein Subselect, der das in einem einzigen Schritt erledigt.

                  - Sven Rautenberg

                  --
                  My sssignature, my preciousssss!
                  1. Man kann aber eine gruppierte Tabelle nicht wieder auf die Ausgangstabelle joinen, weil GROUP BY erst nach dem JOIN wirksam wird. Man müßte sich das Ergebnis von GROUP BY also abspeichern, wieder einlesen, und darauf dann JOIN anwenden. Und genau das ist ein Subselect, der das in einem einzigen Schritt erledigt.

                    Hm, ich habe gerade mal gesucht und dies hier gefunden:
                    http://www.little-idiot.de/mysql/mysql-118.html (letztes Beispiel)

                    Da werden JOIN und GROUP BY miteinander kombiniert. Ich habe mal folgenden Test durchgeführt:

                    Tabelle1:
                    index | p_id | k_name

                    Die Tabelle enthält Namen, die einer p_id zugeordnet sind. Eine p_id kann mehrfach vorkommen, ggf. mit gleichem Namen.

                    Tabelle2:
                    eltern_id | name

                    Die Tabelle enthält Informationen zu p_id (eltern_id ist die Verknüpfung). Wenn ich jetzt folgende Abfrage ausführe, um zu erfahren, welche Eltern wieviele Kinder gleichen Namens (hier "Willi") haben:

                    SELECT  
                      COUNT(a.k_name) AS Anzahl,  
                      b.name AS Elternname  
                    FROM Tabelle1 AS a  
                      LEFT JOIN Tabelle2 AS b  
                      ON a.p_id = b.eltern_id  
                    WHERE a.k_name = "Willi"  
                    GROUP BY a.p_id
                    

                    erhalte ich keine Fehlermeldung, sondern folgende Ergebnistabelle:

                    Anzahl | Elternname  
                    -------------------  
                    1      | Meier  
                    2      | Schultze
                    

                    Und es stimmt, zu Meier gehört 1 Willi, zu Schultze gehören 2 Willis. Oder bin ich da jetzt völlig auf dem Holzweg?

                    Siechfred

                    1. Hallo Siechfred,

                      SELECT

                      COUNT(a.k_name) AS Anzahl,
                        b.name AS Elternname
                      FROM Tabelle1 AS a
                        LEFT JOIN Tabelle2 AS b
                        ON a.p_id = b.eltern_id
                      WHERE a.k_name = "Willi"
                      GROUP BY a.p_id

                      
                      >   
                      > erhalte ich keine Fehlermeldung, sondern folgende Ergebnistabelle:  
                        
                      wie ich diesen Bug, euphemistisch als Optimierung bezeichnet, hasse.  
                      GROUP BY b.name ist erforderlich!  
                        
                      
                      > ~~~
                      
                      Anzahl | Elternname  
                      
                      > -------------------  
                      > 1      | Meier  
                      > 2      | Schultze
                      
                      

                      Und es stimmt,

                      zufällig! Ja, zufällig! Rein zufällig! Nicht vorhersagbar. Lies die MySQL-Doku, http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-fields.html:

                      <zitat>
                      In standard SQL, you would have to add customer.name to the GROUP BY clause. In MySQL, the name is redundant if you do not run with the ONLY_FULL_GROUP_BY SQL mode enabled.

                      Do not use this feature if the columns you omit from the GROUP BY part are not unique in the group! You get unpredictable results.
                      </zitat>

                      Reicht dir der zweite Absatz?

                      zu Meier gehört 1 Willi, zu Schultze gehören 2 Willis. Oder bin ich da jetzt völlig auf dem Holzweg?

                      Ja. Völlig!

                      Freundliche Grüße

                      Vinzenz

      2. Jedes Ereignis wird also nur einmal gezählt, obwohl das Ereignis 1 (Startaufstellung) allein 20 Mal vorkommt. Woran mag dies liegen? Stoppt die Abfrage nach einem Durchlauf?

        Das DISTINCT ist hier nicht nötig:

        SELECT  
          COUNT(ereignis) AS anzahl,  
          ereignis  
        FROM  
          tabellenname  
        WHERE  
          spieler_id = '$id'  
        GROUP BY  
          ereignis
        

        Sorry, Denkfehler :-)

        Siechfred