nilsfad: Unterschiedliche Funktionsweise der GROUP-BY-Klausel

Hallo Forum,

es geht um MySQL in Kombination mit PHP, und zwar programmiere ich da gerade an einem Forum und bin auf ein kleines "Problem" gestossen das sich wie folgt äußert:
Das Select-Statement zum Anzeigen der Beitragsübersicht mit "Count" der Antworten auf jedes Topic produziet auf meinem Mac Mini zuhause erwartungsgemäße Ergebnisse, wenn ich meine Schöpfung jedoch auf meinen Test-Webserver im Netz lade, auf dem wohl eine ältere MySQL Version läuft, baut die Group-By Klausel wohl plötzlich "Mist".

Hier das Statement:
$query = "SELECT prb_request.request_number, prb_request.hierarchy_location, request, author, category, last_name, first_name, date_format(date_posted, '%d.%m.%y, %k:%i Uhr') AS fmt_time, COUNT(*) - 1 AS CommentCount FROM (prb_request INNER JOIN prb_user ON prb_user.login_name LIKE prb_request.author) LEFT JOIN prb_request_category ON prb_request.request_number LIKE prb_request_category.request_number GROUP BY IF(LEFT(hierarchy_location,LOCATE('.',hierarchy_location) - 1) = '',hierarchy_location, LEFT(hierarchy_location, LOCATE('.', hierarchy_location) - 1)) $orderby";

Erwartungsgemäss sollte dies eine Tabelle sämtlicher Themen aller Kategorien mit Spalte für Anzahl der Antworten ausgeben. Auf dem Test-Webserver mit älterer MySQL Version jedoch "wählt" die Group-By Klausel allerdings eine falsche Zeile aus der Ergebnismenge, und zwar meist irgendeine Antwort, anstatt des übergeordneten Themas.
Nur zum Verständnis, ich handhabe es momentan so, dass Themen und Antworten in der selben Tabelle gespeichert sind, nur dass Antworten sich halt dadurch auszeichnen, dass sie keiner Kategorie zugeordnet sind und einen anderen "hierarchy_tag" haben.
Da es auf meinem Rechner zuhause ja erwartungsgemäß klappt, gehe ich davon aus, dass mein Statement so schonmal in Ordnung ist, allerdings würde ich gerne die Abwärtskompatibilität zu älteren MySQL Versionen herstellen.

Weiß jemand vielleicht etwas zu dieser "Thematik" wo die Group-By Klausel ein Bündel von Zeilen unter EINER verkehrten Zeile zusammenfasst? Was kann man dagegen tun?

  1. Hallo

    Das Select-Statement zum Anzeigen der Beitragsübersicht mit "Count" der Antworten auf jedes Topic produziet auf meinem Mac Mini zuhause erwartungsgemäße Ergebnisse,

    unvorhersagbare Ergebnisse, sagt das Handbuch :-)

    wenn ich meine Schöpfung jedoch auf meinen Test-Webserver im Netz lade, auf dem wohl eine ältere MySQL Version läuft, baut die Group-By Klausel wohl plötzlich "Mist".

    Nö. Zulässige Ergebnisse, sagt das Handbuch (gleiche Seite).

    SELECT  
        prb_request.request_number,  
        prb_request.hierarchy_location,  
        request,  
        author,  
        category,  
        last_name,  
        first_name,  
        date_format(date_posted, '%d.%m.%y, %k:%i Uhr') AS fmt_time,  
        COUNT(*) - 1 AS CommentCount  
    FROM (prb_request  
    INNER JOIN prb_user  
    ON prb_user.login_name LIKE prb_request.author)  
    LEFT JOIN prb_request_category ON prb_request.request_number  
    LIKE prb_request_category.request_number  
    GROUP BY IF(LEFT(hierarchy_location,LOCATE('.',hierarchy_location) - 1) = '',hierarchy_location, LEFT(hierarchy_location, LOCATE('.', hierarchy_location) - 1))  
    ORDER BY irgendwas
    

    Da Du nach keiner einzigen vorhandenen Spalte gruppierst, sind die Ergebnisse in allen Feldern außer COUNT(*) zufälliger Natur.

    Erwartungsgemäss sollte dies eine Tabelle sämtlicher Themen aller Kategorien mit Spalte für Anzahl der Antworten ausgeben.

    Wieso?

    Da es auf meinem Rechner zuhause ja erwartungsgemäß klappt,

    zufälligerweise das ergibt, was Du gerne hättest.

    gehe ich davon aus, dass mein Statement so schonmal in Ordnung ist,

    Du irrst.

    allerdings würde ich gerne die Abwärtskompatibilität zu älteren MySQL Versionen herstellen.

    Weiß jemand vielleicht etwas zu dieser "Thematik" wo die Group-By Klausel ein Bündel von Zeilen unter EINER verkehrten Zeile zusammenfasst?

    Du siehst das falsch. GROUP BY liefert zurück, was es zurückliefern darf. Ja, ich habe hier im Forum die Schlampigkeit von MySQL bezüglich solcher SQL-Anweisungen wie Deinem bemängelt. Ich sehe dies nicht als Feature sondern als Bug. Jedes andere mir bekannte Datenbankmanagementsystem weist ein solches Statement als fehlerhaft zurück, in dem nicht nach allen Spalten gruppiert wird, in denen _keine_ Aggregatfunktion verwendet wird.

    Was kann man dagegen tun?

    Das hängt von Deiner MySQL-Version ab. Ist sie älter als 4.1, dann hast Du Pech gehabt. Ist sie mindestens eine 4.1, so könntest Du Dein Ergebnis höchstwahrscheinlich mit einem Subselect erreichen.

    Damit man Dir besser helfen kann, gib' Deine Tabellen mit ein paar Beispieldatensätzen an  - und das erwartete Ergebnis. Und natürlich Deine MySQL-Version :-)

    Freundliche Grüße

    Vinzenz

    1. Das hängt von Deiner MySQL-Version ab. Ist sie älter als 4.1, dann hast Du Pech gehabt. Ist sie mindestens eine 4.1, so könntest Du Dein Ergebnis höchstwahrscheinlich mit einem Subselect erreichen.

      Damit man Dir besser helfen kann, gib' Deine Tabellen mit ein paar Beispieldatensätzen an  - und das erwartete Ergebnis. Und natürlich Deine MySQL-Version :-)

      Bei mir zuhause läuft "5.0.21-standard" und der Test-Server fährt "3.23.58".

      Die Tabelle "prb_request" mit den Beiträgen und Antworten ist wie folgt beschrieben
      +--------------------+---------------------------+------+-----+---------+----------------+
      | Field              | Type                      | Null | Key | Default | Extra          |
      +--------------------+---------------------------+------+-----+---------+----------------+
      | request_number     | int(11)                   | NO   | PRI | NULL    | auto_increment |
      | hierarchy_location | varchar(255)              | NO   |     | NULL    |                |
      | request            | text                      | NO   |     | NULL    |                |
      | status             | enum('active','answered') | NO   |     | NULL    |                |
      | author             | varchar(20)               | NO   |     | NULL    |                |
      | date_posted        | datetime                  | NO   |     | NULL    |                |
      | date_modified      | datetime                  | YES  |     | NULL    |                |
      | date_answered      | datetime                  | YES  |     | NULL    |                |
      +--------------------+---------------------------+------+-----+---------+----------------+

      prb_request_category so:
      +----------------+-------------+------+-----+---------+-------+
      | Field          | Type        | Null | Key | Default | Extra |
      +----------------+-------------+------+-----+---------+-------+
      | request_number | int(11)     | NO   |     | NULL    |       |
      | category       | varchar(20) | NO   |     | NULL    |       |
      +----------------+-------------+------+-----+---------+-------+

      die Spalte "hierarchy_location" in der ersten Tabelle ist etwas "tricky", weil ich die dazu benutze festzustellen, welche Antwort sich auf welche andere Antwort oder Beitrag bezieht. Das ganze sieht aus wie ein herkömmliches Inhaltsverzeichnis wie
      1
      1.1
      1.2
      1.3
      2
      2.1
      2.1.1
      2.1.2
      usw.
      Ist etwas umständlich, aber eine Rekursive lösung war mir einfach zu kompliziert ;)

      Kann man da jetzt noch irgendwas machen außer die Anzahl der Antworten in jeweils separaten Anfragen festzustellen? :/

      1. Hallo

        Bei mir zuhause läuft "5.0.21-standard" und der Test-Server fährt "3.23.58".

        Oh je, die 3.23.58 ist eher jenseits von Gut und Böse :-(

        die Spalte "hierarchy_location" in der ersten Tabelle ist etwas "tricky", weil ich die dazu benutze festzustellen, welche Antwort sich auf welche andere Antwort oder Beitrag bezieht. Das ganze sieht aus wie ein herkömmliches Inhaltsverzeichnis wie

        1
        1.1
        1.2
        1.3
        2
        2.1
        2.1.1
        2.1.2

        Verstehe ich das richtig:

        Zu Beitrag 1 gibt es drei direkte Antworten
        Zu Beitrag 2 gibt es eine direkte Antwort
        Zu Beitrag 2.1 gibt es zwei direkte Antworten,
        zu allen anderen Beiträgen gibt es keine Antwort.

        Wäre das in etwa Dein Ziel:

        -----------
        1         3
        1.1       0
        1.2       0
        1.3       0
        2         1
        2.1       2
        2.1.1     0
        2.1.2     0

        dazu noch die Kategorie, autor, ..., die alle direkt von der Spalte request_number abhängen. Habe ich das richtig verstanden?

        Eine Frage noch zu den Tabellen prb_request und prb_request_category:
        Gibt es Einträge in prb_request, zu denen es _keine_ Einträge in prb_request_category gibt?
        Wieviele Einträge zu einem Eintrag in prb_request kann es in prb_request_category geben? Einen oder mehrere?

        Freundliche Grüße

        Vinzenz

        1. 1
          1.1
          1.2
          1.3
          2
          2.1
          2.1.1
          2.1.2

          Verstehe ich das richtig:

          Zu Beitrag 1 gibt es drei direkte Antworten
          Zu Beitrag 2 gibt es eine direkte Antwort
          Zu Beitrag 2.1 gibt es zwei direkte Antworten,
          zu allen anderen Beiträgen gibt es keine Antwort.

          Ganz genau!

          Wäre das in etwa Dein Ziel:


          1         3
          1.1       0
          1.2       0
          1.3       0
          2         1
          2.1       2
          2.1.1     0
          2.1.2     0

          sogar noch "einfacher":
          -----------
          1         3
          1.1       0
          1.2       0
          1.3       0
          2         3
          2.1       0
          2.1.1     0
          2.1.2     0

          Es geht ja nur um die Anzeige der Beiträge auf oberster Ebene, und gezählt werden sämtliche Antworten auf allen nachfolgenden Ebenen.

          dazu noch die Kategorie, autor, ..., die alle direkt von der Spalte request_number abhängen. Habe ich das richtig verstanden?

          Ja.

          Eine Frage noch zu den Tabellen prb_request und prb_request_category:
          Gibt es Einträge in prb_request, zu denen es _keine_ Einträge in prb_request_category gibt?

          Ja, das sind alle Antworten, also Zeilen in prb_request, wo die hierarchy_location mindestens einen "." (Punkt) enthält.

          Wieviele Einträge zu einem Eintrag in prb_request kann es in prb_request_category geben? Einen oder mehrere?

          Nur einen, ein Thema kann maximal nur in einer Kategorie aufgeführt sein.

          Wäre schön, wenn du einen Ausweg wüsstest.

          1. Hallo

            1
            1.1
            1.2
            1.3
            2
            2.1
            2.1.1
            2.1.2

            sogar noch "einfacher":

            ich vermute noch einfacher:

            1         3
            2         3

            denn

            Es geht ja nur um die Anzeige der Beiträge auf oberster Ebene, und gezählt werden sämtliche Antworten auf allen nachfolgenden Ebenen.

            dazu noch die Kategorie, autor, ..., die alle direkt von der Spalte request_number abhängen. Habe ich das richtig verstanden?

            Wieviele Einträge zu einem Eintrag in prb_request kann es in prb_request_category geben? Einen oder mehrere?

            Nur einen, ein Thema kann maximal nur in einer Kategorie aufgeführt sein.

            das ist gut.

            Wäre schön, wenn du einen Ausweg wüsstest.

            Wenn man keine Subselects verwenden kann, wie im Fall von MySQL 3.23.x (oder auch 4.0.x), dann versucht man das Ergebnis durch Joins hinzubekommen. Glücklicherweise hängen bei Dir _alle_ Spalten in der Ergebnismenge direkt von der Spalte request_number ab, die in der Ergebnismenge vorhanden ist.

            Im ersten Schritt erzeugen wir über einen Join die notwendigen Datensätze:
            Du möchtest alle Beiträge der obersten Ebene haben, dazu alle Antworten auf diesen Beitrag. Der Trick, einen Beitrag als Antwort auf sich selbst zu sehen - und am Ende die Anzahl der "Antworten" um eine zu verringern - hilft, um auch die Beiträge zu bekommen, auf die es noch keine Antwort gab.

            SELECT  
              pr1.request_number,  
              pr1.hierarchy_location,  
              pr1.request,  
              pr1.author,  
              prc.category,  
              pu.last_name,  
              pu.first_name,  
              date_format(date_posted, '%d.%m.%<, %k:%i Uhr') AS fmt_time,  
              
              -- und nun noch den Beitrag oberster Ebene, auf den sich der  
              -- Beitrag bezieht  
              -- Diese Spalte sollte überflüssig sein, sie dient mehr als  
              -- Anschauungsobjekt, wie das ganze funktioniert  
              IF (LOCATE('.', pr2.hierarchy_location),  
                LEFT(pr2.hierarchy_location, LOCATE('.', pr2.hierarchy_location) - 1),  
                pr2.hierarchy_location) AS Beitrag  
              
            FROM prb_request pr1  
              
            -- Wir sind nur an den Beiträgen der obersten Ebene interessiert,  
            -- diese haben einen korrespondierenden Eintrag in prb_request_category  
            INNER JOIN prb_request_category prc  
            ON prb1.request_number = prc.request_number  
              
            -- holen uns noch die Daten zum Verfasser des Beitrags  
            -- Jeder Beitrag hat einen Verfasser :-)  
            INNER JOIN prb_user pu  
            ON pr1.author = pu.login_name  
              
            -- jetzt kommt der Trick, wobei ich nicht weiß, ob MySQL diese Bedingung  
            -- gelten läßt.  
            -- Verknüpfe die Beitragstabelle mit sich selbst und zwar über den Anteil  
            -- von hierarchy_location, der den Startbeitrag angibt.  
            -- Beachte, dass wir auf Seiten von pr1 bereits alle Startbeiträge  
            -- herausgefischt haben  
            INNER JOIN prb_request pr2  
            ON pr1.hierarchy_location =  
                (IF (LOCATE('.', pr2.hierarchy_location),  
                  LEFT(pr2.hierarchy_location, LOCATE('.', pr2.hierarchy_location) - 1),  
                  pr2.hierarchy_location))  
              
            Im zweiten Schritt zählen wir einfach, wie oft eine request_number vorkommt und gruppieren nach allen Spalten. Diese enthalten je request_number sowieso den gleichen Inhalt, so dass genau das gewünschte übrigbleiben sollte:  
              
            [code lang=sql]SELECT  
              pr1.request_number,  
              pr1.hierarchy_location,  
              pr1.request,  
              pr1.author,  
              prc.category,  
              pu.last_name,  
              pu.first_name,  
              date_format(date_posted, '%d.%m.%<, %k:%i Uhr') AS fmt_time,  
              COUNT(pr1.request_number) - 1 AS CommentCount  
            FROM prb_request pr1  
            INNER JOIN prb_request_category prc  
            ON prb1.request_number = prc.request_number  
            INNER JOIN prb_user pu  
            ON pr1.author = pu.login_name  
            INNER JOIN prb_request pr2  
            ON pr1.hierarchy_location =  
                (IF (LOCATE('.', pr2.hierarchy_location),  
                  LEFT(pr2.hierarchy_location, LOCATE('.', pr2.hierarchy_location) - 1),  
                  pr2.hierarchy_location))  
            GROUP BY  
              pr1.request_number,     -- in MySQL sind diese Felder überflüssig  
              pr1.hierarchy_location, -- alle anderen DBMS, die ich kenne, wollen  
              pr1.request,            -- diese haben.  
              pr1.author,             --  
              prc.category,           -- Meiner Meinung nach zu Recht.  
              pu.last_name,  
              pu.first_name,  
              date_format(date_posted, '%d.%m.%<, %k:%i Uhr')  
            ORDER BY  
              pr1.request_number -- oder was immer Du haben willst
            

            In Abhängigkeit davon, ob die JOIN-Bedingung akzeptiert wird (ich habe das nicht getestet), sollte dieses Statement das von Dir gewünschte Ergebnis liefern. Eventuell darfst Du noch den einen oder anderen Flüchtigkeitsfehler eliminieren.

            Freundliche Grüße

            Vinzenz

            1. Tja, was soll ich sagen, ich bin SEHR beeindruckt.
              Ich blicke zwar noch nicht ganz durch, "warum", aber dein Statement bringt nun TATSÄCHLICH das gewünschte Ergebnis auf BEIDEN MySQL Versionen.
              Respekt, da kennt sich wer WIRKLICH aus. :-)

              1. Hallo,

                zunächst mal danke für die Blumen, aber ...

                Ich blicke zwar noch nicht ganz durch, "warum",

                ... aus diesem Grund ist das nur die halbe Miete.

                aber dein Statement bringt nun TATSÄCHLICH das gewünschte Ergebnis auf BEIDEN MySQL Versionen.
                Respekt, da kennt sich wer WIRKLICH aus. :-)

                Mein Ziel ist es eigentlich, dass der Fragesteller versteht, wie eine Lösung funktioniert, damit dieser in Zukunft es allein hinbekommt.

                Als grundsätzliche Lektüre empfehle ich Dir die JOIN-Artikel in SELFHTML Aktuell:
                Einführung Joins
                Fortgeschrittene Jointechniken

                Der Weg zu der Lösung Deiner Problemstellung in Einzelschritten. Ein paar weniger wichtige Spalten habe ich der Übersichtlichkeit halber weggelassen.

                Zuerst die Beispieltabellen:

                1. prb_user

                login_name  first_name  last_name
                ---------------------------------
                abel        Abel        Mensch
                adam        Adam        Mensch
                eva         Eva         Mensch
                kain        Kain        Mensch
                seth        Seth        Mensch

                2. prb_request
                   request_number ist mit rn abgekürzt, hierarchy_location mit hl :-)

                rn  hl      request                      author
                -----------------------------------------------
                1   1       Staub                        adam
                2   1.1     Rippe                        eva
                3   1.2     Die erste Zeugung            kain
                4   1.3     Das Wunder Mensch            seth
                5   2       Mmh, ein Apfel               eva
                6   2.1     Lecker                       adam
                7   2.1.1   Ohne den gäbs mich nicht     kain
                8   2.1.2   Mich auch nicht              abel
                9   3       Vegetarier leben gefährlich  abel

                3. prb_request_category
                   request_number ist mit rn abgekürzt

                rn  category
                ------------------
                1   Erschaffung
                5   Nahrung
                9   Risikofaktoren

                Es folgt der Zusammenbau der SELECT-Statements:

                a) Ganz einfacher Beginn.
                   Auswählen dreier Spalten aus der Tabelle prb_request

                SELECT  
                  pr1.request_number rn,      -- Aliasnamen für kürzere Schreibweisen  
                  pr1.hierarchy_location hl,  
                  pr1.request  
                FROM prb_request pr1
                

                Ergebnis:

                rn  hl     request
                --------------------------------------
                1   1      Staub
                2   1.1    Rippe
                3   1.2    Die erste Zeugung
                4   1.3    Das Wunder Mensch
                5   2      Mmh, ein Apfel
                6   2.1    Lecker
                7   2.1.1  Ohne den gäbs mich nicht
                8   2.1.2  Mich auch nicht
                9   3      Vegetarier leben gefährlich

                b) Verknüpfe die Tabelle prb_request mit einem INNER JOIN mit der Tabelle
                   prb_request, damit wir ausschließlich die Beiträge der ersten Ebene erhalten.
                   Wir erinnern uns:

                Wieviele Einträge zu einem Eintrag in prb_request kann es in prb_request_category geben? Einen oder mehrere?
                Nur einen, ein Thema kann maximal nur in einer Kategorie aufgeführt sein.

                SELECT  
                  pr1.request_number rn,  
                  pr1.hierarchy_location hl,  
                  pr1.request,  
                  prc.category  
                FROM prb_request pr1  
                INNER JOIN prb_request_category prc  
                ON pr1.request_number = prc_request_number
                

                führt zu dem Ergebnis

                rn  hl  request                      category
                ------------------------------------------------
                1   1   Staub                        Erschaffung
                5   2   Mmh, ein Apfel               Nahrung
                9   3   Vegetarier leben gefährlich  Risikofaktoren"

                c) Im nächsten Schritt holen wir uns die Detailinformationen zum Autor,
                   dazu dient ein INNER JOIN mit der Tabelle prb_user:

                SELECT  
                  pr1.request_number rn,  
                  pr1.hierarchy_location hl,  
                  pr1.request,  
                  pr1.author,  
                  prc.category,  
                  pu.last_name l_name,  
                  pu.first_name f_name  
                FROM prb_request pr1  
                INNER JOIN prb_request_category prc  
                ON pr1.request_number = prc.request_number  
                INNER JOIN prb_user pu  
                ON pr1.author = pu.login_name
                

                Ergebnis:

                rn  hl  request                      author  category        l_name  f_name
                ---------------------------------------------------------------------------
                1   1   Staub                        adam    Erschaffung     Mensch  Adam
                5   2   Mmh, ein Apfel               eva     Nahrung         Mensch  Eva
                9   3   Vegetarier leben gefährlich  abel    Risikofaktoren  Mensch  Abel

                d) Nun kommen wir zum Selfjoin, der uns das Zählen
                   der Antworten ermöglichen wird. Jeder Eintrag unseres Zwischenergebnisses wird mit dem
                   jedem Eintrag verknüpft, der diesen Eintrag als "Starteintrag" hat. Das ganze ist etwas
                   trickreich, daher ausführlich der Zwischenschritt:

                SELECT  
                    request_number AS rn,  
                    hierarchy_location AS hl,  
                    -- Bestimme die Position des ersten Punktes in hierarchy_location:  
                    [link:http://dev.mysql.com/doc/refman/4.1/en/string-functions.html#id3068426@title=LOCATE]('.', pr2.hierarchy_location) AS erster_punkt,  
                    -- Wenn es einen solchen Punkt gibt  
                    --     Dann gib den Teilstring bis zum ersten Punkt zurück,  
                    --     d.h. den Anteil, der den Startbeitrag angibt  
                    -- Sonst  
                    --     muss es ein Beitrag erster Ebene sein, d.h. selbst Startbeitrag  
                    --     Gib dessen hierarchy_location zurück  
                    [link:http://dev.mysql.com/doc/refman/4.1/en/control-flow-functions.html#id3065568@title=IF] (LOCATE('.', pr2.hierarchy_location),  
                        [link:http://dev.mysql.com/doc/refman/4.1/en/string-functions.html#id3068149@title=LEFT](pr2.hierarchy_location, LOCATE('.', pr2.hierarchy_location) - 1),  
                        pr2.hierarchy_location) AS Beitrag  
                FROM prb_request pr2
                

                rn  hl     erster_punkt  Beitrag
                --------------------------------
                1   1      0             1
                2   1.1    2             1
                3   1.2    2             1
                4   1.3    2             1
                5   2      0             2
                6   2.1    2             2
                7   2.1.1  2             2
                8   2.1.2  2             2
                9   3      0             3

                Für Beiträge der obersten Ebene liefert LOCATE den Wert 0 zurück, dies entspricht in MySQL
                dem boolschen Wert false. D.h. IF liefert mit Hilfe von LEFT stets
                die hierarchy_location des zugehörigen Startbeitrags zurück. Als JOIN-Bedingung nutzen wir
                daher die Gleichheit des hierarchy_location des Startbeitrags und der berechneten Spalte
                "Beitrag".

                e) In Aktion:

                SELECT  
                  pr1.request_number rn,  
                  pr1.hierarchy_location hl,  
                  pr1.request,  
                  pr1.author,  
                  prc.category,  
                  pu.last_name l_name,  
                  pu.first_name f_name,  
                  IF (LOCATE('.', pr2.hierarchy_location),  
                    LEFT(pr2.hierarchy_location, LOCATE('.', pr2.hierarchy_location) - 1),  
                    pr2.hierarchy_location) AS Beitrag  
                FROM prb_request pr1  
                INNER JOIN prb_request_category prc  
                ON pr1.request_number = prc.request_number  
                INNER JOIN prb_user pu  
                ON pr1.author = pu.login_name  
                INNER JOIN prb_request pr2  
                ON pr1.hierarchy_location =  
                  (IF (LOCATE('.', pr2.hierarchy_location),  
                     LEFT(pr2.hierarchy_location, LOCATE('.', pr2.hierarchy_location) - 1),  
                     pr2.hierarchy_location))
                

                rn  hl  request                      author  category        l_name  f_name  Beitrag
                ------------------------------------------------------------------------------------
                1   1   Staub                        adam    Erschaffung     Mensch  Adam    1
                1   1   Staub                        adam    Erschaffung     Mensch  Adam    1
                1   1   Staub                        adam    Erschaffung     Mensch  Adam    1
                1   1   Staub                        adam    Erschaffung     Mensch  Adam    1
                5   2   Mmh, ein Apfel               eva     Nahrung         Mensch  Eva     2
                5   2   Mmh, ein Apfel               eva     Nahrung         Mensch  Eva     2
                5   2   Mmh, ein Apfel               eva     Nahrung         Mensch  Eva     2
                5   2   Mmh, ein Apfel               eva     Nahrung         Mensch  Eva     2
                9   3   Vegetarier leben gefährlich  abel    Risikofaktoren  Mensch  Abel    3

                Du siehst, dass man nun wunderbar nach allen Spalten gruppieren kann - und das Auftreten
                der request_number zählen kann. Nicht vergessen: am Schluß von der Anzahl 1 abziehen, da
                derzeit ja der Startbeitrag auch als Antwort gezählt wird. Die Spalte Beitrag diente im
                vorhergehenden Zwischenschritt nur zur Illustration, wir lassen sie jetzt einfach weg.

                f) Wir kommen somit zu der Anweisung, die uns das gewünschte Resultat liefert:

                SELECT  
                  pr1.request_number rn,  
                  pr1.hierarchy_location hl,  
                  pr1.request,  
                  pr1.author,  
                  prc.category,  
                  pu.last_name l_name,  
                  pu.first_name f_name,  
                  COUNT(pr1.request_number) - 1 AS CommentCount  
                FROM prb_request pr1  
                INNER JOIN prb_request_category prc  
                ON pr1.request_number = prc.request_number  
                INNER JOIN prb_user pu  
                ON pr1.author = pu.login_name  
                INNER JOIN prb_request pr2  
                ON pr1.hierarchy_location =  
                  (IF (LOCATE('.', pr2.hierarchy_location),  
                     LEFT(pr2.hierarchy_location, LOCATE('.', pr2.hierarchy_location) - 1),  
                     pr2.hierarchy_location))  
                GROUP BY  
                  pr1.request_number,  
                  pr1.hierarchy_location,  
                  pr1.request,  
                  pr1.author,  
                  prc.category,  
                  pu.last_name,  
                  pu.first_name
                

                rn  hl  request                      author  category        l_name  f_name  CommentCount
                -----------------------------------------------------------------------------------------
                1   1   Staub                        adam    Erschaffung     Mensch  Adam     3
                5   2   Mmh, ein Apfel               eva     Nahrung         Mensch  Eva      3
                9   3   Vegetarier leben gefährlich  abel    Risikofaktoren  Mensch  Abel     0

                Ich hoffe, Du liest dieses Posting und verstehst anhand der Einzelschritte,
                warum die Anweisung das gewünschte Ergebnis zurückliefert.

                Freundliche Grüße

                Vinzenz

                1. Ja Hallo,

                  ich schau hier selbstverständlich noch rein, war momentan noch damit beschäftigt, dein umfangreiches SQL-Statement, das mir so geholfen hat, zu "studieren". ;) Deine Ausführungen hier werden mir sicher dabei helfen, vielen Dank.

                  Hallo,

                  zunächst mal danke für die Blumen, aber ...

                  Ich blicke zwar noch nicht ganz durch, "warum",

                  ... aus diesem Grund ist das nur die halbe Miete.

                  aber dein Statement bringt nun TATSÄCHLICH das gewünschte Ergebnis auf BEIDEN MySQL Versionen.
                  Respekt, da kennt sich wer WIRKLICH aus. :-)

                  Mein Ziel ist es eigentlich, dass der Fragesteller versteht, wie eine Lösung funktioniert, damit dieser in Zukunft es allein hinbekommt.

                  Als grundsätzliche Lektüre empfehle ich Dir die JOIN-Artikel in SELFHTML Aktuell:
                  Einführung Joins
                  Fortgeschrittene Jointechniken

                  Der Weg zu der Lösung Deiner Problemstellung in Einzelschritten. Ein paar weniger wichtige Spalten habe ich der Übersichtlichkeit halber weggelassen.

                2. Ja, nach einiger Lektüre kann ich es schon nachvollziehen.
                  Aber auf sowas muss man auch erstmal drauf kommen. :-)

                  1. Hallo

                    Ja, nach einiger Lektüre kann ich es schon nachvollziehen.

                    schön das zu lesen. *freu*

                    Aber auf sowas muss man auch erstmal drauf kommen. :-)

                    Ich hab' ja auch etwas Übung :-)

                    Freundliche Grüße

                    Vinzenz

            2. yo Vinz,

              deine beiträge sind immer so schön strukutiert. wie lange brauchst du eigentlich für das tippen dieses letzten beitrages ? ich würde ewigkeiten dafür brauchen....

              Ilja

              1. Hallo Ilja,

                deine beiträge sind immer so schön strukutiert.

                danke für das Lob.

                wie lange brauchst du eigentlich für das tippen dieses letzten beitrages ?

                ich hab' nicht auf die Uhr geschaut, aber eine Viertelstunde werde ich schon benötigt haben.

                Freundliche Grüße

                Vinzenz

                1. yo,

                  ich hab' nicht auf die Uhr geschaut, aber eine Viertelstunde werde ich schon benötigt haben.

                  ich hätte dafür mindestens eine halbe stunde gebraucht und dann auch noch mit meinen typischen fählern.....

                  schnell und strukturiert, nicht schlecht der specht.

                  Ilja