SQL - Join und SubSelect
bearbeitet von Rolf BHallo Casablanca,
zum einen - bist Du sicher, dass Du für die Kombination von UserLanguages, Tasks und Languages einen LEFT JOIN brauchst? Sicherlich wird es keinen Task geben, der eine unbekannte LanguageId hat. Und es wird auch keinen UserLanguage Satz geben, der eine unbekannte LanguageId hat.
Insofern wirst Du wohl keine Ergebniszeilen bekommen, wo aus der Tasks- oder Language-Abfrage nichts herauskommt. Und es wäre fachlich auch nicht sinnvoll, glaube ich. Man sollte keinen LEFT JOIN formulieren, wo fachlich ein INNER JOIN angemessen ist.
Soweit dazu. Zu deinem Problem: Du könntest einen LEFT JOIN auf die UserTasks machen (hier ist ein LEFT JOIN korrekt, weil es ja auch keine Treffer geben kann) und dann STATUS IS NULL OR STATUS=0 prüfen. Es ist bei umfangereicheren Queries übrigens oft lesbarer, den Tabellen Aliasnamen zu geben, dann schreibt man nicht so viel und das Statement ist übersichtlicher. Ich mach das mal...
~~~sql
SELECT ul.UserId, l.Language, t.TaskId
FROM UserLanguages ul
Join Tasks t ON ...
Join Languages l ON ...
Left Join UserTasks ON ut.UserId=ul.UserId
AND ut.TaskId=t.TaskId
AND (ut.status IS NULL OR ut.status = 1)
WHERE ul.UserId = VARIABLE
~~~
Aber ich glaube, es ist einfacher (und vermutlich auch effizienter), wenn Du nicht nach den Sätzen fragst, die Du haben willst, sondern nach denen, die Du nicht haben willst: mit `NOT EXISTS (...)`
~~~sql
SELECT ul.UserId, l.Language, t.TaskId
FROM UserLanguages ul
Join Tasks t ON ...
Join Languages l ON ...
WHERE ul.UserId = VARIABLE
AND NOT EXISTS (SELECT * FROM UserTasks ut
WHERE ut.UserId=ul.UserId AND ut.TaskId=t.TaskId
AND ut.Status=0)
~~~
Probier beides aus, mach Explains, miss die Performance. Verwende das, was besser läuft oder was Du besser verstehst 😉
_Rolf_
--
sumpsi - posui - obstruxi
SQL - Join und SubSelect
bearbeitet von Rolf BHallo Casablanca,
zum einen - bist Du sicher, dass Du einen LEFT JOIN brauchst?
Sicherlich wird es keinen Task geben, der eine unbekannte LanguageId hat. Und es wird auch keinen UserLanguage Satz geben, der eine unbekannte LanguageId hat.
Insofern wirst Du wohl keine Ergebniszeilen bekommen, wo aus der Tasks- oder Language-Abfrage nichts herauskommt. Und es wäre fachlich auch nicht sinnvoll, glaube ich. Man sollte keinen LEFT JOIN formulieren, wo fachlich ein INNER JOIN angemessen ist.
Soweit dazu. Zu deinem Problem: Du könntest einen LEFT JOIN auf die UserTasks machen (hier ist ein LEFT JOIN korrekt, weil es ja auch keine Treffer geben kann) und dann STATUS IS NULL OR STATUS=0 prüfen. Es ist bei umfangereicheren Queries übrigens oft lesbarer, den Tabellen Aliasnamen zu geben, dann schreibt man nicht so viel und das Statement ist übersichtlicher. Ich mach das mal...
~~~sql
SELECT ul.UserId, l.Language, t.TaskId
FROM UserLanguages ul
Join Tasks t ON ...
Join Languages l ON ...
Left Join UserTasks ON ut.UserId=ul.UserId
AND ut.TaskId=t.TaskId
AND (ut.status IS NULL OR ut.status = 1)
WHERE ul.UserId = VARIABLE
~~~
Aber ich glaube, es ist einfacher (und vermutlich auch effizienter), wenn Du nicht nach den Sätzen fragst, die Du haben willst, sondern nach denen, die Du nicht haben willst: mit `NOT EXISTS (...)`
~~~sql
SELECT ul.UserId, l.Language, t.TaskId
FROM UserLanguages ul
Join Tasks t ON ...
Join Languages l ON ...
WHERE ul.UserId = VARIABLE
AND NOT EXISTS (SELECT * FROM UserTasks ut
WHERE ut.UserId=ul.UserId AND ut.TaskId=t.TaskId
AND ut.Status=0)
~~~
Probier beides aus, mach Explains, miss die Performance. Verwende das, was besser läuft oder was Du besser verstehst 😉
_Rolf_
--
sumpsi - posui - obstruxi