MySQL Problem mit LEFT JOIN
Snafu
- datenbank
Hallo!
Ich habe ein Problem mit einer MySQL Abfrage.
Ich möchte folgendes realisieren:
*) Aus meiner Foren Tabelle (forum_forums) die ForumID (id), den Admin-Status (admin) den Forumnamen (title) und die Beschreibung (description)
*) aus meiner Posts Tabelle (forum_posts) die PostID (id), den Namen des Posters (name), den Zeitpunkt des Postings (datetime [ja, ich weiß ...]) und die TopicID des Posts (topic_id)
*) aus meiner Topic Tabelle den namen (topic)
holen.
Mein bester Versuch war dieser hier
--- MySQL Anfang ---
SELECT f.id, f.admin, f.title, f.description, t.topic AS lastpost_topic, p.name AS lastpost_name, p.datetime AS lastpost_datetime
FROM forum_forums AS f
LEFT JOIN (
SELECT forum_id, topic_id, name, `datetime`
FROM forum_posts
) AS p ON f.id = p.forum_id
LEFT JOIN (
SELECT id, topic
FROM forum_topics
ORDER BY id DESC
) AS t ON p.topic_id = t.id
--- MySQL Ende ---
Allerdings zeigt er mir dann alle Posts zu jedem Forum an und nicht nur den letzen.
Wenn ich jetzt die Abfrage bei den Posts abändere (LIMIT 1 hinzufüge)
--- MySQL Anfang ---
...
LEFT JOIN (
SELECT forum_id, topic_id, name, `datetime`
FROM forum_posts LIMIT 1
) AS p ON f.id = p.forum_id
...
--- MySQL Ende ---
dann erhalte ich nur den aller letzen Post von allen Foren und nicht den letzten Post von jedem Forum. Ich müsste also irgendwie LIMIT __anzahl der foren__ machen damit das funktionniert.
Ich habe vollstes Vertrauen in eure hilfe :)
PS: Wenn ihr mir auch sagen könnt, wie ich in dieser Abfrage auch die Anzahl der Topics und Posts mitliefern kann wäre das perfekt.
Hallo!
*) Aus meiner Foren Tabelle (forum_forums) die ForumID (id), den Admin-Status (admin) den Forumnamen (title) und die Beschreibung (description)
*) aus meiner Posts Tabelle (forum_posts) die PostID (id), den Namen des Posters (name), den Zeitpunkt des Postings (datetime [ja, ich weiß ...]) und die TopicID des Posts (topic_id)
langsam, langsam. Ich zitiere Dich weiter unten:
Allerdings zeigt er mir dann alle Posts zu jedem Forum an und nicht nur den letzen.
Ja eben. Du möchtest das letzte Posting zu jedem Forum. Das ist etwas anderes als Deine Beschreibung.
Wenn ich jetzt die Abfrage bei den Posts abändere (LIMIT 1 hinzufüge)
was ein völlig untaugliches Mittel zu Deinem Problem ist.
Ich habe vollstes Vertrauen in eure hilfe :)
Normalerweise auch zu Recht.
PS: Wenn ihr mir auch sagen könnt, wie ich in dieser Abfrage auch die Anzahl der Topics und Posts mitliefern kann wäre das perfekt.
Das ist ein einfaches Standardproblem, dessen Lösung im Wesentlichen eine korrelierte Unterabfrage ist.
Subselects (Unterabfragen) unterstützt MySQL seit Version 4.1. Du solltest also Deine Version angeben.
Freundliche Grüße
Vinzenz
Das ist ein einfaches Standardproblem, dessen Lösung im Wesentlichen eine korrelierte Unterabfrage ist.
Subselects (Unterabfragen) unterstützt MySQL seit Version 4.1. Du solltest also Deine Version angeben.
Ich hab MySQL 5 laufen, von dem her sollte es also kein Problem sein.
Den Thread den du gepostet hast werde ich mir gleich ansehen. Zuerst muss ich diesem Cordon bleu einmal helfen die endliche Reise in meinen Magen zu bestreiten ^^
Wenn ich jetzt die Abfrage bei den Posts abändere (LIMIT 1 hinzufüge)
was ein völlig untaugliches Mittel zu Deinem Problem ist.
Das habe ich ja auch geschrieben (naja, mehr oder weniger :) )
Ich hab mir deinen Post in dem anderen Thread angesehen und diese 2 Sätze (eigentlich ein Satz und 3 Wörter :D ) haben mir einen Klaps auf den Hinterkopf beschert.
Benötigt wird genau ein Datensatz zu einem bestimmten Kriterium, zum Beispiel der neueste Beitrag pro Autor. Mit GROUP BY ...
Habe also GROUP BY in meine Abfrage mit eingebaut und siehe da, es funktionniert. Hätte ich auch von selbst draufkommen können, wenn ich meine Grauen Zellen etwas mehr bemüht hätte :D
Die Abfrage sieht nun so aus:
--- MySQL Anfang ---
SELECT f.id, f.admin, f.title, f.description, t.topic AS lastpost_topic, p.name AS lastpost_name, p.datetime AS lastpost_datetime
FROM forum_forums AS f
LEFT JOIN (
SELECT forum_id, topic_id, name, `datetime`
FROM carpenoctem_posts
GROUP BY forum_id
ORDER BY id DESC
) AS p ON f.id = p.forum_id
LEFT JOIN (
SELECT id, topic
FROM forum_topics
ORDER BY id DESC
) AS t ON p.topic_id = t.id
--- MySQL Ende ---
Falls ich hier zwar das richtige Ergebnis erhalte aber es eigentlich viel einfacher geht bitte sofort schreien (im übertragenen Sinne natürlich).
So, jetzt muss ich nur noch das "Problem" mit der Anzahl der Posts, Threads lösen.
So,
meine endgültige Lösung ist nun doch etwas anders als die Zwischenlösungen. Diese Abfrage tut nun endlich das, was ich haben will und das bedeute ich bekomme:
*) forum_forums: id, admin, title, description
*) Subabfragen: Anzahl der Topics und Posts in einem Forum
*) forum_posts: name, datetime
*) forum_topics: topic
zurückgeliefert.
--- MySQL Start ---
SELECT f.id, f.admin, f.title, f.description,
COALESCE( (SELECT COUNT( * )
FROM forum_topics
WHERE forum_id = f.id
GROUP BY forum_id ) , 0) AS total_topics,
COALESCE( (SELECT COUNT( * )
FROM forum_posts
WHERE forum_id = f.id
GROUP BY forum_id ) , 0) AS total_posts,
t.topic AS lastpost_topic,
p.name AS lastpost_name, p.`datetime` AS lastpost_datetime
FROM forum_forums AS f
LEFT JOIN (
SELECT forum_id, topic_id, name, `datetime`
FROM forum_posts AS x
WHERE id = (
SELECT MAX( id )
FROM forum_posts
WHERE forum_id = x.forum_id )
) AS p ON p.forum_id = f.id
LEFT JOIN (
SELECT id, topic
FROM forum_topics
) AS t ON t.id = p.topic_id
ORDER BY f.admin DESC , f.id ASC
--- MySQL End ---
Sagt mir bitte, ob das eine vernünftie Abfrage ist oder ob man das leichter lösen könnte.
Hallo
Sagt mir bitte, ob das eine vernünftie Abfrage ist
frag EXPLAIN.
oder ob man das leichter lösen könnte.
Gut möglich. Mir ist schleierhaft, was Du vorhast.
Wie soviele Fragesteller hier im Forum kannst Du Dir leider überhaupt nicht
vorstellen, dass der geneigte Antworter überhaupt nichts darüber weiß, was
in Deinen Tabellen steht, und was Du aus welchem Grund als Ergebnis haben
möchtest.
Grundsätzlich ist es eine ausgezeichnete Idee, bei solchen Fragen seine
Tabellen anzugeben, dazu ein paar Beispieldatensätze zu jeder Tabelle, und
damit zu erläutern, wie das Modell aussieht und was es abbildet.
Es ist einfach enorm aufwendig, aus ein paar SQl-Statements - oft dazu
fehlerhaft oder unnötig kompliziert - den Zusammenhang zu nachzuvollziehen.
Du hast es meisterhaft verstanden, diesen Zusammenhang zu verheimlichen.
Ich habe mir erneut Dein Ausgangspostin angeschaut:
Es gibt also etwas wie
- Foren
- Postings
- Topics
Jedem Forum können viele Postings zugeordnet sein.
Jedes Posting ist genau einem Forum zugeordnet.
Jedes Topic kann vielen Postings zugeordnet sein.
Jedes Posting ist genau einem Topic zugeordnet.
Also eine ganz normale n:m-Beziehung zwischen Foren und Topics, wobei
das Bindeglied, die Postings selbst über Eigenschaften verfügen.
Hab' ich das soweit richtig verstanden?
Nun möchtest Du folgendes wissen:
Gib mir zu jedem Forum ein paar forumsspezifische Angaben
(d.h. Werte aus Feldern der Forentabelle),
dazu die Anzahl der Postings in diesem Forum,
die Anzahl der behandelten Topics,
und zum guten Schluß noch das neueste Posting mit Detailangaben
wie Name des Posters, Topicangabe und Zeitpunkt.
Wenn ich auch das richtig verstanden habe, dann kommt mir Dein Vorgehen
reichlich umständlich vor. Natürlich begehst Du auch einen typischen
Anfängerfehler, indem Du das neueste Posting an der höchsten ID erkennen
willst. Nein, das neueste Posting trägt den neuesten Zeitstempel. Das ist
doch genauso logisch wie einleuchtend.
Bevor ich noch mehr Zeit investiere, möchte ich wissen, ob meine Annahmen
richtig sind - und ich möchte Beispieldaten in Tabellen sehen.
Freundliche Grüße
Vinzenz
Hallo!
Grundsätzlich ist es eine ausgezeichnete Idee, bei solchen Fragen seine
Tabellen anzugeben, dazu ein paar Beispieldatensätze zu jeder Tabelle, und
damit zu erläutern, wie das Modell aussieht und was es abbildet.
Oh das habe ich natürlich vergessen, darauf hättest du mich gleich am Anfang hinweisen sollen :)
Also meine forum_forums Tabelle sieht so aus:
+-----+-------------------+---------------------+
| id | title | description |
+-----+-------------------+---------------------+
| 1 | Allgemein | Allgemeine Sachen |
| 2 | Sport | Sport blabla |
| . | .... | ...... |
+-----+-------------------+---------------------+
Meine forum_topics Tabelle:
+----+----------+--------------+---------------------+-------------+
| id | forum_id | firstpost_id | topic | datetime |
+----+----------+--------------+---------------------+-------------+
| 1 | 1 | 1 | Hallo alle zusammen | 2007-04-0...|
| 2 | 1 | 2 | Das ist ein Test | ...... |
| 3 | 2 | 3 | Fussball EM | ...... |
| . | . | . | ..... | ...... |
+----+----------+--------------+---------------------+-------------+
Meine forum_posts Tabelle (auch wieder mit datetime aber das geht sich nicht schön im textarea aus):
+----+----------+----------+---------------------+--------+----------------+
| id | forum_id | topic_id | title | name | text |
+----+----------+----------+---------------------+--------+----------------+
| 1 | 1 | 1 | Hallo alle zusammen | Fabio | Hallo! ... |
| 2 | 1 | 2 | Das ist ein Test | Alex | Test, test |
| 3 | 2 | 3 | Fussball EM | Gast | ich = AUT = :( |
| . | . | . | ....... | .... | ......... |
+----+----------+----------+---------------------+--------+----------------+
Es ist einfach enorm aufwendig, aus ein paar SQl-Statements - oft dazu
fehlerhaft oder unnötig kompliziert - den Zusammenhang zu nachzuvollziehen.
Du hast es meisterhaft verstanden, diesen Zusammenhang zu verheimlichen.
*schäm*
Ich habe mir erneut Dein Ausgangspostin angeschaut:
...
Hab' ich das soweit richtig verstanden?
Du solltest Hellseher werden :D
Nun möchtest Du folgendes wissen:
...
Wieder Volltreffer
Wenn ich auch das richtig verstanden habe, dann kommt mir Dein Vorgehen
reichlich umständlich vor.
Das habe ich geahnt :D
Nein, das neueste Posting trägt den neuesten Zeitstempel. Das ist
doch genauso logisch wie einleuchtend.
Schon aber logisch ist auch, dass je später das Posting dazukommt, desto größer ist dessen ID.
Freundliche Grüße
Ebenfalls :)
Ach mist, habe etwas vergessen.
Bei jeder Tabelle ist ein Feld "admin" welches 0 oder 1 ist.
Wenn es 1 ist dann ist es ein "internes" was auch immer es ist :)
Ich würde übrigens gerne noch wissen ob es eine "bessere" Abfrage für mein Problem gibt.