Vinzenz Mai: MySQL: GROUP-BY und Ergebnisse in nicht gruppierten Spalten

Beitrag lesen

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