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