Hi,
jetzt wird dein Query schon klarer, aber ich verstehe immer noch nicht, warum den User und den Comment zusammen in einem SELECT joinst. Aber vermutlich ist auch hier wieder ein Verständnisproblem:
Möchtest du beim Hinzufügen eines Users auch einen Kommentar zu dieser Aktion speichern? Dann verstehe in nämlich warum du das in einem SELECT versuchst, das müsste man dann aber auch anders aufbauen.
Ich meinte bisher immer nur den Kommentar, den du zu einem Task schreibst, unabhängig einer Aktivität (also User hinzufügen / entfernen, Statusänderungen, ...). Wenn du zu den Aktivitäten auch Kommentare loggen willst, dann klar, brauchst du ein Nullable Feld Comment. Das darfst du dann aber nicht mit deinen Task-Comments verwechseln!
Und noch ein Nachtrag zu deinem Post gestern Abend, wenn du zusätzlich auf Teilprojekte (Tasks?) loggen willst, dann machst du in die Log-Tabelle außer resource_id zusätzlich task_id rein, als Nullable. Hier sind NULL-Werte wieder von Vorteil: Ist der Task Null gilt die Aktivity für das gesamte Projekt, ansonsten nur für den Task innerhalb des Projekts.
Außerdem: Ein Log sollte auch nur loggen und für mehr sollte die Tabelle nicht verwendet werden. Also bei Statusänderungen und einer Historie bitte nicht alten und neuen Status in die Log Tabelle schreiben. Mach eine Tabelle Statusänderung mit den Feldern Id, Projekt Id, Task Id (Nullable), State. Den alten Status brauchst du nicht zusätzlich speichern, da er ja als vorheriger Eintrag in der Historie verfügbar ist (Normalformen beachten). Falls es aber dann mit Joins und Subselects zu aufwendig wird, kannst du natürlich auch den old_state immer mit speichern. In die Log Tabelle kommt dann nur noch die Id als Referenz ins Info Feld. Und da ist dann auch wieder der Timestamp der Änderung. So hat alles seinen Platz.
Im Endeffekt stelle ich es mir (vereinfacht) so vor:
Tabelle Users:
Tabelle Projects:
Tabelle Projects_Users (Verknüpfungstabelle der n:m Beziehung):
Tabelle States:
Tabelle Tasks:
- id
- project_id
- name
- description
Tabelle StateHistory:
- id
- state_id
- project_id
- task_id
Tabelle TaskComments:
Tabelle Activities:
Tabelle ActivityLog:
- id
- project_id
- task_id (NULLABLE)
- user_id
- info
- comment (NULLABLE)
- timestamp
Für deine Abfragen musst du dann eben immer die Log-Tabelle mit einbeziehen. Da bekommst du die Timestamps der Aktivitäten her. Wenn du z.B. die letzte Statusänderung von Projekt 1, Task 3 sehen willst, dann musst du in der Log nach project_id = 1, zusätzlich task_id = 3
und actvity_id = {ID FÜR STATUSÄNDERUNG} filtern und dann die beiden neuesten Einträge holen. Der neuere der beiden ist dann der neue Status und der andere ist der vorherige (demnach alte) Status, die status_id ist dann jeweils im Info-Feld.
Außerdem kannst du, falls gewünscht, zu jedem Log einen Kommentar dazu schreiben. Wenn deine TaskComments Tabelle nicht noch für etwas anderes benötigt wird, bzw. wenn du nur Kommentar-Texte bei Activities speicherst, kannst du die TaskComments Tabelle natürlich auch weg lassen, weil der Kommentartext ja dann im Log verfügbar ist.
Ich hoffe, das zeigt nun etwas klarer, wie ich mir den Anwendungsfall von dir vorstelle und wie ich denke, dass man ihn designtechnisch am elegantesten lösen kann.
Gruß
Daniel