Hi,
stellen wir uns mal vor, wir möchten ein Forum bauen und dort die Themen in einer Baumstruktur darstellen. Um den Baum möglichst ohne Rekursion zu erstellen haben wir zwei Felder, posx und posy. posy gibt die vertikale Reihenfolge (von oben nach unten) an, und posx die Tiefe der Einrückung.
Wichtig bei der Baumdarstellung ist nun, dass wir wissen möchten, ob der Besucher (username) gewisse Beiträge schon gelesen hat oder nicht. Das soll möglichst schnell und effizient geschehen.
Ein sturrer, uneinsichtiger Kumpel von mir meinte, es sei das Beste eine zusätzliche Tabelle anzulegen und einen zusammengesetzen primären Schlüssel auf ThemenID und Username zu legen und dann drei Felder a 60 chars zu haben, die als Bitflags dienen. Somit kann ein Thema max. 180 Beiträge haben (eigentlich ausreichend) udn er kann über Bitberechnungen schnell abfragen, ob ein Benutzer ein Post gelesen hat oder nicht. Für mich sieht das aber sehr sehr umständlich und nahezu schwachsinnig aus *g*. Schauen wir es uns doch einmal selbst an:
SELECT
forum_posts.postid,
forum_posts.posx,
forum_posts.posttopic,
forum_posts.nickname,
forum_posts.posttime,
( IF(forum_posts.postid<60,
forum_postviews.mask60 & POW(2,postid)=POW(2,postid),
IF(forum_posts.postid<120,
forum_postviews.mask120 & POW(2,postid-60)=POW(2,postid-60),
forum_postviews.mask180 & POW(2,postid-120)=POW(2,postid-120)
)
)
) as readed
FROM
forum_postviews,
forum_posts
WHERE
forum_posts.boardid=1
AND forum_posts.id=1
AND forum_postviews.boardid=1
AND forum_postviews.id=1
AND forum_postviews.nickname='besucher'
ORDER BY
forum_posts.posy ASC,
forum_posts.posttime ASC;
Ich steuere eine Lösung an, bei der ich mich ebenfalls darauf berufe für die vertikale Sortierung eine Spalte posy und für die Einrückung eine Spalte posx zu wählen, allerdings möchte ich die Verwaltung der gelesenen Beiträge - in meinen Augen - verbessern:
Es soll auch wieder eine extra Tabelle geben. Dort soll der zusammengesetzte Primärschlüssel aber über die Felder ThemenID, PostID und Username liegen und zusätzlich soll ein Feld mit der Eigenschaft time hinzukommen, um zu sehen, wann der Besucher das letzte mal den Beitrag gelesen hat. Das ergibt dann in meinen Augen ein Performanceschub, da die Abfrage wesentliche einfacher gestaltet ist:
SELECT
forum_posts.id,
forum_posts.posx,
forum_posts.topic,
forum_posts.time,
forum_posts.username,
IF(forum_postviews.time IS NOT NULL, forum_postviews.time, 0) as readtime
FROM
forum_posts
LEFT JOIN
forum_users
ON forum_posts.username=forum_users.username
LEFT JOIN
forum_postviews
ON forum_posts.id=forum_postviews.postid
AND forum_postviews.username='besucher'
WHERE
forum_posts.boardid=1
AND forum_posts.threadid=1
ORDER BY
forum_posts.posy ASC,
forum_posts.time ASC;
Meine Frage, wer liegt denn nun richtig?! :o)
Oder, um von der Frage nach richtig / falsch wegzukommen, welcher Ansatz löst die Aufgabe mit dem effizienteren Ergebnis?! :o)
In meinen Augen ist die Bildung eines kathesischen Produkts, so wie er es bei seiner Lösung macht, nicht das richtige, da hier erstmal unnötig viele Datensätze gebildet werden, um dann die richtigen auszuwählen, wohingegen ich nur die Posts auswähle und von diesen ausgehend nur die Abfrage, die ich auch benötige. Ist das so richtig?
Danke für Kritik / Meinungen / Antworten.
Gruss
Stefan