Tach!
Noch ein paar Anmerkungen eher kosmetischer Natur. Die kannst du letzlich auch ignorieren, denn so wie du das hast, ist es nicht weniger gut.
SELECT ug.gruppe
FROM user_in_gruppen AS ug
WHERE ug.user = 3
Beim Alias ist es nicht erforderlich (und in einigen SQL-Dialekten auch nicht vorgesehen), das Schlüsselwort AS zu notieren.
Hier ist sogar das komplette Alias ug entbehrlich. (Ebenso das ag auf der nächsten Ebene.) Das ist nur unnötige Tipparbeit und es ergibt sich auch im weiteren Verlauf keine Notwendigkeit, durch das Alias für Klarheit zu sorgen. Die Subquerys bilden hier komplette und eigenständige Einheiten und die Bezeichner sind innerhalb dieser bereits durch ihren Feldnamen eindeutig.
(Der nächste Teil hat keinen Bezug zu deinem Anwendungsfall.)
Etwas anders wäre die Sachlage, wenn es sich um eine korrellierte Subquery handelte. Dabei wird in der Subquery für die WHERE-Bedingung ein Feld aus der Haupt-Query hinzugezogen. Das ist der Fall, wenn zum Beispiel der User nicht ein fester Wert sein soll, sondern der Wert aus einem Feld der Hauptquery sein soll. Konkretes Beispiel: Gib mir alle Artikel(-ID), zu denen (keine) User existieren.
SELECT artikel FROM artikel_fuer_gruppen WHERE EXISTS (SELECT * FROM user_in_gruppen WHERE gruppe = artikel_fuer_gruppen.gruppe)
Hier wird die Subquery für jeden Datensatz der artikel_fuer_gruppen ausgeführt. Beim IN() reicht eine einmalige Ausführung. Für den "keine"-Fall wäre das EXISTS durch ein NOT EXISTS auszutauschen. Statt des * kann auch was beliebig anderes stehen. Die Feldliste im Subquery-SELECT wird bei EXISTS ignoriert. Deswegen selektiert auch ein * nicht zu viel. Aber zurück zum Alias. Das Feld "gruppe" ist zweimal vorhanden. Es reicht jedoch, das aus der äußeren Query eindeutig anzusprechen. (Hier mit dem Tabllennamen, ein Alias wäre jedoch auch ok.) Das alleinstehende "gruppe" bezieht sich auf die nächstliegende Tabelle, also hier user_in_gruppen.
Und dazu sagtest Du bei Deiner letzten Antwort, ich soll das mit IN(...) lösen. Das war mir etwas klarer, als ich mir ein Beispiel dazu im Manual angesehen habe.
Ich hätte da auf [http://dev.mysql.com/doc/refman/5.6/en/any-in-some-subqueries.html@title=Subqueries with ANY, IN, or SOME] nachgeschaut und nicht im Optimizer-Kapitel, aber hat ja offensichtlich auch geholfen.
Zuerst habe ich nicht verstanden, wieso da die Artikeln 2, 3 und 4 doppelt gelistet werden. Aber es ist, wenn man nachdenkt, eh klar. Ein Mal werden die Artikel-IDs ausgegeben, weil sie für die Usergruppe 2 freigegeben sind und ein Mal, weil sie gleichzeitig auch für die Usergruppe 3 freigegeben sind.
Oder anders gesagt: Es gibt in der Tabelle artikel_fuer_gruppen Datensätze für die Gruppe 2 und welche für die Gruppe 3. Beide Datensatzmengen findest du im Ergebnis. Klarer sichtbar wird das, wenn du in der Kontroll-Ausgabe zusätzlich zur Artikel-ID auch noch die Gruppen-ID ausgibst (oder einfach * scheibst).
Da ich natürlich keinen Artikel doppelt ausgeben möchte, kommt jetzt Dein 3. Satz ins Spiel:
Wähle alle Artikel, deren ID in der Ergebnismenge der vorherigen Frage ist.
Beim IN() ist es egal, wie oft dort ein Wert drinsteht, Hauptsache er ist mindestens einmal vorhanden.
Hmm, eben hab ich noch bei einer Query angemerkt, dass sie zu viele Zwischenergebnisse erzeugt und jetzt hab ich selbst den Fall. Wie red ich mich da jetzt raus? Vielleicht so: Hier werden nur ein paar "kleine" ID-Werte und keine kompletten Ergebnisdatensätze erzeugt, da fallen die überflüssigen Werte nicht so sehr ins Gewicht.
dedlfix.