Danny: MYSQL Abfrage - group by vermute ich

Hallo zusammen,

ich hoffe Ihr könnt mir helfen.
Ich habe eine DB mit den Spalten name, nummer, status.

Beispiel:

Klaus - 654 - 1
Bernd - 889 - 0
Peter - 458 - 0
Klaus - 123 - 1
Bernd - 874 - 0
Peter - 478 - 1
Klaus - 511 - 0
Bernd - 741 - 1
Peter - 659 - 0

Nun möchte ich folgendes ausgeben:

Klaus hat mit Status 0: 511
Klaus hat mit Status 1: 654, 123

Bernd hat mit Status 0: 889, 874
Bernd hat mit Status 1: 741

Peter hat mit Status 0: 458, 659
Peter hat mit Status 1: 478

Leider habe ich keinen Ansatz das in einem abzufragen.

Danke für eure Hilfe

Danny

  1. Hi!

    Nun möchte ich folgendes ausgeben:
    Klaus hat mit Status 0: 511
    Klaus hat mit Status 1: 654, 123

    Gruppiere über Name und Status. Auf die restlichen Spalten (in dem Fall nur noch nummer) solltest du nur mit Aggregatfunktionen zugreifen, sonst ist das Ergebnis undefiniert eins aus der Gruppe. In deinem Fall sollte GROUP_CONCAT() die Funktion sein, die dir das gewünschte Ergebnis liefern. Du bekommst damit alle Nummern mit einem Trennzeichen separiert als einen Wert zurück.

    Alternativ kannst du die Zusammenfassung auch in der abfragenden Programmierumgebung machen. Die Abfrage muss dazu nur alle Datensätze sortiert (nach Name und Status) liefern. Beim Auswerten nimmst du dann eine Technik namens Gruppenwechsel.

    Lo!

    1. Hallo,

      habe mir die Abfrage nach deinen Vorgaben versucht zu erstellen:

        
      $query="SELECT *, GROUP_CONCAT(DISTINCT name ORDER BY nummer DESC SEPARATOR ' ') from tabelle GROUP BY name, status";  
        
      $result=mysql_query($query,$db);  
      while ($ausgabe=mysql_fetch_object($result))  
      {  
      echo "$ausgabe->name $ausgabe->nummer<br />";  
      }  
      
      

      So bekomme ich nur eine "nummer" ausgegeben.

      1. Hi!

        habe mir die Abfrage nach deinen Vorgaben versucht zu erstellen:

        Der PHP-Code ist für dein Problem nicht weiter wichtig, den kannst du weglassen.

        SELECT *, GROUP_CONCAT(DISTINCT name ORDER BY nummer DESC SEPARATOR ' ') from tabelle GROUP BY name, status

        SELECT * fragt alle Felder ab, auch die, auf die du im Prinzip nur mit Aggregatfunktionen zugreifen solltest. MySQL lässt das zwar zu, andere DBMS sind strenger und werten das als Fehler. Gib lieber nur die Felder an, über die du gruppierst und die Aggregatfunktionen. Dein eigentliches Problem ist aber die Formulierung des GROUP_CONCAT()-Ausdrucks.

        GROUP_CONCAT(DISTINCT name ORDER BY nummer DESC SEPARATOR ' ')

        Die Gruppierung ist schon mit der GROUP-BY-Klausel erledigt. GROUP_CONCAT() ist nur noch auf die zusammenzufassenden Daten anzuwenden, also nicht auf name sondern auf nummer. Hast du doppelte Nummern innerhalb einer Gruppierung? Also, kommt beispielsweise die 511 bei Klaus-0 doppelt vor? Wenn ja, dann brauchst du das DISTINCT, ansonsten nicht. Wenn sie bei Klaus-1 nochmal vorkommt, ist das eine andere Gruppe und von DISTINCT unberührt.

        Lo!

        1. Hi,

          ich komme nicht weiter.
          Dann muss die Abfrage so aussehen?

          SELECT *, GROUP_CONCAT(nummer SEPARATOR ' ') from tabelle

          Das Ergebnis sagt "Nein".
          Doppelte Nummern habe ich nicht-daher brauche ich DISTINCT nicht.

          1. Hi!

            ich komme nicht weiter.

            Eigentlich hättest du nur im bereits bestehenden Statement das GROUP_CONCAT korrigieren müssen (sowie das Problem mit dem *, das du anscheinend nicht verstanden hast, was aber in deinem Fall nicht weiter tragisch wäre.)

            Dann muss die Abfrage so aussehen?
            SELECT *, GROUP_CONCAT(nummer SEPARATOR ' ') from tabelle

            Jetzt fehlt die Gruppierung. Ich schreib es mal vollständig hin:

            SELECT name, status, GROUP_CONCAT(nummer ORDER BY nummer DESC SEPARATOR ' ') from tabelle GROUP BY name, status

            Das ORDER BY nummer DESC kannst du weglassen, wenn du es nicht brauchst. Ansonsten sortiert es die Nummern.

            Lo!

            1. Nochmal Hallo,

              und vielen Dank für deine Geduld.
              So wie du es schreibst hatte ich es bereits umgesetzt-aber es wird mir nur eine "nummer" ausgegeben.

              Langsam verzweifel ich... ;-)

              1. Hi!

                So wie du es schreibst hatte ich es bereits umgesetzt-aber es wird mir nur eine "nummer" ausgegeben.

                Tut mir leid, ich kann das nicht nachvollziehen. Wenn ich

                SELECT name, status, CAST(GROUP_CONCAT(nummer ORDER BY nummer DESC SEPARATOR ' ') AS CHAR) FROM danny GROUP BY name, status

                in den phpMyAdmin einkippe, dann bekomme ich

                name status CAST( GROUP_CONCAT( nummer ORDER BY nummer DESC SEPARATOR ' ' ) AS CHAR )
                Bernd 0 889 874
                Bernd 1 741
                Klaus 0 511
                Klaus 1 654 123
                Peter 0 659 458
                Peter 1 478

                Das CAST() ist notwendig, weil der PMA sonst nur ein [BLOB - 7 B] oder [BLOB - 3 B] anzeigt. Im abfragenden Programm ist das Casten aber nicht notwendig.

                Ich kann mir jetzt nur noch vorstellen, dass du bei der Anzeige einen Fehler machst. Vielleicht sowas in der Art:

                <input type=text name=nummer value=<?php echo $row['nummern'] ?>>

                Das ergäbe dann bei Bernd mit Status 0:

                <input type=text name=nummer value=889 874>

                Das Leerzeichen zwischen den beiden Zahlen beendet das value-Attribut, das 874 stellt ein neues Attribut dar und wird vom Browser ignoriert. Richtig in dem Fall wäre:

                <input type="text" name="nummer" value="<?php echo htmlspecialchars($row['nummern']) ?>">

                Probier doch mal dein SQL-Statement in einem Tool wie dem PMA.

                Lo!

                1. Hallo,

                  ich habe nun eine "halbe" Lösung.

                  $query="SELECT name, status, GROUP_CONCAT(nummer SEPARATOR ', ') AS xxx from tabelle GROUP BY name, status";

                  Durch das "AS" kann ich die nummern nun ausgeben.

                  $ausgabe->xxx;

                  Problem ist sie stehen alle mit hintereinander mit "," getrennt-aber wie erkenne ich denn ob status "0" oder "1"?

                  Beste Grüsse

                  Danny

                  1. Problem ist sie stehen alle mit hintereinander mit "," getrennt

                    Das wolltest du doch so?

                    aber wie erkenne ich denn ob status "0" oder "1"?

                    an $ausgabe->status

                  2. Hi!

                    $query="SELECT name, status, GROUP_CONCAT(nummer SEPARATOR ', ') AS xxx from tabelle GROUP BY name, status";
                    Durch das "AS" kann ich die nummern nun ausgeben.
                    $ausgabe->xxx;

                    Das ginge vorher auch, nur etwas umständlicher. Wenn du dir mal mit var_dump($ausgabe) anzeigen lässt, wie so eine Ergebniszeile aussieht (vorher ein <pre> erhöht die Übersichtlichkeit), wäre dir sicher manches klarer. Mach das übrigens auch mal ohne das "AS xxx".

                    Problem ist sie stehen alle mit hintereinander mit "," getrennt-aber wie erkenne ich denn ob status "0" oder "1"?

                    Nicht "," sondern ", ". Leerzeichen sind manchmal fiese kleine Dinger. Unterschätze und missachte sie nicht!

                    Für den Status findest du nach dem Anschauen der var_dump()-Ausgabe garantiert auch eine Lösung. Gegen das Hintereinanderstehen gibt es ebenfalls Wege, nur musst du dazu definieren, wie du es genau haben möchtest. explode() beispielsweise kann daraus ein Array machen.

                    Lo!

              2. So wie du es schreibst hatte ich es bereits umgesetzt

                Nein hast du nicht, trotz dreimaliger Aussage "du sollst nicht SELECT * schreiben", machst du es dennoch wieder.

                aber es wird mir nur eine "nummer" ausgegeben.

                Würdest du nur die Spalten auswählen, welche auch von Relevanz sind, würdest du keine Nummer ausgegeben bekommen (bei vernünftiger Konfiguration sogar eine Fehlermeldung).

                Verpasse der berechneten Spalte einen Alias und greife über den Alias auf diese Spalte zu.

                [code=sql]
                GROUP_CONCAT(...) AS nummern
                [/code]

                [code=php]
                $row->nummern
                [/code]