Problem bei LEFT OUTER JOIN
Johannes Völlinger
- datenbank
Hi!
Da ich nicht aus diesem MYSQL Ergebnis schlau werde, werfe ich diese Frage mal in die Runde.
Bastel gerade ein News Skript mit zwei Tabellen: News und Kommentare. Ich will die Anzahl der Kommentare zu jedem Newsbeitrag anzeigen lassen und nutze einen LEFT OUTER JOIN in Verbindung mit GROUP BY und Count, um dies zu realisieren. Klappt mit drei Testdaten auch so wie erwartet und er gibt die Anzahl richtig aus (3,0,1). Das Problem kommt aber, sobald es mehrere News OHNE Kommentare gibt. Er zeigt mir partu nur EINEN Datensatz an, zu dem es keine Kommentare gibt, alle anderen Nachrichten (ohne Kommentare) werden nicht ins Ergebnis aufgenommen. Woran liegt das und wie kann ich das beheben?
cya
Johannes
Hi,
wie sieht Deine Query aus? Zeig mal! Hört sich nach falschem Parameter für die GROUP-BY-Klausel an...
HTH Robert
Hi,
wie sieht Deine Query aus? Zeig mal! Hört sich nach falschem Parameter für die GROUP-BY-Klausel an...
Also an der Group by Klausel kann nicht liegen, dafür kommt nur das Feld in Frage. Kann auch keinen Logikfehler entdecken, er macht ja auch sonst alles richtig, nur das er mir nicht mehr als einen Datensatz anzeigen will, zu dem es in der "rechten" Tabelle Kommentare keine Datensätze gibt.
Hier der Query:
SELECT news.NEWS_ID, news.Topic, news.Nachricht, news.Verfasser, news.Quelle, news.Datum, count(comment.KOMM_ID) FROM News as news LEFT OUTER JOIN Kommentare AS comment ON news.NEWS_ID=comment.NEWS_ID GROUP BY comment.NEWS_ID ORDER BY news.Datum
Auch mit dem Zusatz "WHERE comment.KOMM_ID IS NULL" gibt er nur einen Datensatz aus, der keinen Kommentar hat (5 müßten es sein)!
Auch das weglassen des "OUTER" aus dem LEFT OUTER JOIN, bringt nichts.
Hallo,
SELECT news.NEWS_ID, news.Topic, news.Nachricht, news.Verfasser, news.Quelle, news.Datum, count(comment.KOMM_ID) FROM News as news LEFT OUTER JOIN Kommentare AS comment ON news.NEWS_ID=comment.NEWS_ID GROUP BY comment.NEWS_ID ORDER BY news.Datum
Zählt MySQL NULL-Werte? Probiere mal:
SELECT news.NEWS_ID, news.Topic, news.Nachricht, news.Verfasser, news.Quelle, news.Datum, count(IFNULL(comment.KOMM_ID,1)) FROM News as news LEFT OUTER JOIN Kommentare AS comment ON news.NEWS_ID=comment.NEWS_ID GROUP BY comment.NEWS_ID ORDER BY news.Datum
viele Grüße
Axel
Zählt MySQL NULL-Werte? Probiere mal:
SELECT news.NEWS_ID, news.Topic, news.Nachricht, news.Verfasser, news.Quelle, news.Datum, count(IFNULL(comment.KOMM_ID,1)) FROM News as news LEFT OUTER JOIN Kommentare AS comment ON news.NEWS_ID=comment.NEWS_ID GROUP BY comment.NEWS_ID ORDER BY news.Datum
Hmhm, ein interessanter Ansatz, das hatte ich noch nicht ausgetestet. Leider kommt auch hier wieder dasselbe Ergebnis wie bei meinem vorherigen LEFT OUTER JOIN auch. Langsam glaube ich, der Fehler liegt nicht im Query ... *weiter grübelt*
cya
Jubbi
Hallo,
dann kann man eigentlich nur versuchen, den Fehler einzugrenzen:
MySQL erlaubt eine vom Standard abweichende Group By Syntax, in der nicht alle ausgewählten Felder mit in die Gruppe oder Aggregatfunkionen aufgenommen werden. So richtig getraut habe ich dem aber noch nie. Machen wir's mal ANSI-standardkonform
SELECT comment.NEWS_ID, count(IFNULL(comment.KOMM_ID,1)) as cnt FROM News as news LEFT OUTER JOIN Kommentare AS comment ON news.NEWS_ID=comment.NEWS_ID GROUP BY IFNULL(comment.NEWS_ID,1) ORDER BY news.Datum
richtige Anzahl? Dann:
SELECT max(news.NEWS_ID), max(news.Topic), max(news.Nachricht), max(news.Verfasser), max(news.Quelle), max(news.Datum), count(IFNULL(comment.KOMM_ID,1)) FROM News as news LEFT OUTER JOIN Kommentare AS comment ON news.NEWS_ID=comment.NEWS_ID GROUP BY IFNULL(comment.NEWS_ID,1) ORDER BY news.Datum
viele Grüße
Axel
Hi,
SELECT news.NEWS_ID, news.Topic, news.Nachricht, news.Verfasser, news.Quelle, news.Datum, count(comment.KOMM_ID)
FROM News as news
LEFT OUTER JOIN Kommentare AS comment ON news.NEWS_ID=comment.NEWS_ID
GROUP BY comment.NEWS_ID
ORDER BY news.Datum
Das left-outer-join-Gedöns verwirrt mich immer; könnte ein Problem darin liegen, daß Du nach dem der Spalte NEWS_ID aus der rechten Tabelle gruppierst? Warum überhaupt? Wie wäre es, den Join über eine WHERE-Bedingung auszuführen (und in den Klauseln GROUP und ORDER nur die Ergebnisspalten zu benennen):
SELECT news.NEWS_ID, news.Topic, news.Nachricht, news.Verfasser, news.Quelle, news.Datum, count(comment.KOMM_ID)
FROM News as news, Kommentare as comment
WHERE news.NEWS_ID = comment.NEWS_ID
GROUP BY NEWS_ID
ORDER BY Datum
?
HTH Robert
Das left-outer-join-Gedöns verwirrt mich immer; könnte ein Problem darin liegen, daß Du nach dem der Spalte NEWS_ID aus der rechten Tabelle gruppierst? Warum überhaupt? Wie wäre es, den Join über eine WHERE-Bedingung auszuführen (und in den Klauseln GROUP und ORDER nur die Ergebnisspalten zu benennen):
Mit dem "normalen" OUTER JOIN kommst du zwar an die Ergebnisse ran die sich in der News UND der Kommentar Tabelle befinden, allerdings brauche ich auch die Datensätze in meinem Result, die keinen Datensatz in der "benachbarten" (rechten) Tabelle haben (sprich: kein Kommentar zur News). Das ist ja auch der eigentlich Sinn des LEFT und RIGHT OUTER JOINS, mal abgesehen von der Tatsache, daß sie schneller ausgeführt werden (kartesisches Produkt).
Mit nem normalen Wald und Wiesen Join bräuchte ich schon zwei einzelne Abfragen, um an das gewünschte Ergebnis zu kommen und das möchte ich auf jeden Fall vermeiden.
cya
Johannes
Hi,
Mit dem "normalen" OUTER JOIN kommst du zwar an die Ergebnisse ran die sich in der News UND der Kommentar Tabelle befinden, allerdings brauche ich auch die Datensätze in meinem Result, die keinen Datensatz in der "benachbarten" (rechten) Tabelle haben (sprich: kein Kommentar zur News).
Ja klar, ich sollte besser nachdenken, bevor ich antworte. Was war mit dem anderen Hinweis, den Tabellen-Alias aus der GROUP-BY-Klausel zu nehmen: GROUP BY NEWS_ID statt GROUP BY comment.NEWS_ID? Das scheint mir problematisch...
HTH Robert
Was war mit dem anderen Hinweis, den Tabellen-Alias aus der GROUP-BY-Klausel zu nehmen: GROUP BY NEWS_ID statt GROUP BY comment.NEWS_ID? Das scheint mir problematisch...
Nene, den Alias brauchste, sonst spuckt dir MYSQL nen Fehler aus (zweideutig). Ich verwende den Schlüssel NEWS_ID ja sowohl in der Tabelle News (Primary Key), als auch in der Tabelle Kommentar (Foreign Key). Deshalb braucht die Datenbank auch ne eindeutige Zuordnung über den Alias Namen. Keine Ahnung, warum er immer nur einen der 5 News mit NULL-Wert (ohne Kommentar) anzeigen will und nicht alle. >_<
cya
Johannes
Hi,
Nene, den Alias brauchste, sonst spuckt dir MYSQL nen Fehler aus (zweideutig). Ich verwende den Schlüssel NEWS_ID ja sowohl in der Tabelle News (Primary Key), als auch in der Tabelle Kommentar (Foreign Key). Deshalb braucht die Datenbank auch ne eindeutige Zuordnung über den Alias Namen. Keine Ahnung, warum er immer nur einen der 5 News mit NULL-Wert (ohne Kommentar) anzeigen will und nicht alle. >_<
mir fehlt der Glaube... GROUP BY und ORDER BY orientieren sich an den Spalten des Result sets (ich habe in keinem SQL-Dialekt jemals dort Tabellen-Aliase verwendet gesehen), dort gibt es keine Zweideutigkeit. Hättest die bei NEWS_ID-Spalten im Ergebnis, so müßte mindestens eine einen Alias erhalten, um keine Fehler zu werfen.
Hast Du es einmal ohne Alias in GROUP BY versucht? Oder vielleicht den Spaltenindex (GROUP BY 1), wenn Dir das lieber ist? Das würde mich überzeugen...
HTH Robert
Hast Du es einmal ohne Alias in GROUP BY versucht? Oder vielleicht den Spaltenindex (GROUP BY 1), wenn Dir das lieber ist? Das würde mich überzeugen...
Da ich eh keine Ideen mehr habe, ziehe ich gerne jede Möglichkeit in Betracht. ^^
*umspechtet*
*Abfrage abschickt*
*blöd guckt*
Ich weiß nicht, ob ich mich jetzt freuen oder schreien soll. *sich fürs schreien entscheidet* ^^
Es kommt jetzt genau das Ergebnis raus, das ich erwartet, aber vorher nicht bekommen habe! >_< Ich habe sowohl in SQL als auch in MySQL immer den Alias Namen verwendet und nie Probleme gehabt. Selbst in meinen Onlinedokumentationen und Büchern verwenden sie in ihren GROUP BY Beispielen den Alias in Verbindung mit dem Feld-Namen. Wieso zum Kuckuck spinnt aber MySQL so rum??? Er hat mir vorher auch die richtige Anzahl an Datensätzen ausgespuckt, nur wollte er partu nicht mehr als einen anzeigen. >_<
Egal, was solls. -_-' Es läuft jetzt und das ist alles was ich wollte. Danke dir für den Tip, auch wenn ich jetzt mit nem großen Fragezeichen weiter am Newsskript basteln werde. :-)
cya
Johannes
Hi,
*sich fürs schreien entscheidet* ^^
schön.
Ich habe sowohl in SQL als auch in MySQL immer den Alias Namen verwendet und nie Probleme gehabt. Selbst in meinen Onlinedokumentationen und Büchern verwenden sie in ihren GROUP BY Beispielen den Alias in Verbindung mit dem Feld-Namen. Wieso zum Kuckuck spinnt aber MySQL so rum???
Ich habe GROUP BY immer als auf Ergebnisspalten angewendet angesehen, welche keinen Bezug mehr zu ihren Ursprungstabelle haben. Deshalb betrachte ich den Alias in der Klausel auch als Fremdkörper. Gegenüber ANSI hat bietet MySQL allerdings die Möglichkeit, GROUP BY auch auf nicht im Result set enthaltene Spalten anzuwenden, dann wird gegebenenfalls der Tabellen-Alias erforderlich.
HTH Robert
versuchs mal ohne das OUTER...einfach nur n Left Join