[MySQL] Nicht enthaltene Datensätze ausgeben (JOIN)

(damit wir bei den keksen bleiben).

Sehr gut.

Nur nochmal für mich:
ID = Die des eigneloggten users
UserID = Die UserID, welche in der Tabelle Users hinterlegt ist (3-stellig), welcher den Keks bekommt.

Der eingeloggte User soll eine Liste ALLER User erhalten (außer sich selbst), denen er noch keinen Keks gegeben hat (Zeit wird's).
Das müsste doch bedeuten, man müsse erst die User-Tabelle abgrasen und alle User von dort (außer sich selbst) selektieren, und danach die rauswerfen, die in Tabelle logs mit dem eingeloggten user zusammen stehen.

SQL:
SELECT user.userid
FROM user
LEFT JOIN log ON user.userid = log.userid
WHERE u.userid != 1 AND l.id != 1

WHERE u.userid != 1 soll den eingeloggten User aus der ersten Ergebnismenge rausnehmen.
AND l.id != soll aus der log-Ergebnismenge alle User rausnehmen, denen er schon den Keks gegeben hat.
Was ich jetzt aber so gar nicht raffe ist die Relation zwischen Tabelle user und Tabelle log. In deinem Beispiel hattest du die beiden über die jeweiligen ids verbunden, nicht über die userid aus Tabelle user.

Könntest du eventuell noch die einzelnen Spalten der Tabellen erklären? Wofür ist id jeweils genau da? In der User-Tabelle würde es keinen Sinn ergeben, wenn sie auch die ID des eingeloggten Users wäre...

@ unter mir: du bist mal ruhig mit deinem doofen Subselect ;) (BASHING! YEAH!!)
 
Zuletzt bearbeitet von einem Moderator:
  • Gefällt mir
Reaktionen: SP7
@Lime Wusste gar nicht dass SELECT so mächtig ist :D
hat geklappt danke Mr. Lime :)
Ist genau dass, was ich mühsam probiert habe zu umschreiben :p

@para_noid hätte die Spalten besser benennen sollen :S
Auch ein grosses danke an dich, falls du allerdings mir noch ein JOIN example liefern könntest für meine Frage würde mich dies auch sehr erfreuen :)
 
Was ich noch nicht kapiert habe ist die Tabelle User.
Wozu hast du zwei Spalten mit IDs? ID und UserID?
Eigentlich reicht eine. ^^
 
also, du hast da ein Problem, wenn die Tabellen die Inhalte haben, die du hier zeigst.
Denn in der Tabelle User hast du unter ID 2 die UserID 352 ==>Hans
In der Log-Tabelle hast du unter ID 2 die UserID 355 und 356.

Wenn ich nachgucken möchte, wer nun die Nummer 355 ist und gehe über die ID: User.2=Log.2 dann lande ich beim Hans, aber 355 ist "buch", da die ID 2 bei Log die Nummer 355 abgespeichert hat.

Und das verwirrt mich^^ Ich glaub, du hättest den Fremdschlüssel in der Log-Tabelle auf userid setzen sollen und nicht auf die id.
 
Zuletzt bearbeitet:
Was ich noch nicht kapiert habe ist die Tabelle User.
Wozu hast du zwei Spalten mit IDs? ID und UserID?
Eigentlich reicht eine. ^^

Zuerst muss ich sagen es dient nur als schnittstelle.
Die ids sind miteinander unabhängig, die ID ist die vom User also auf der Page, die UserID kommt von extern, damit die Schnittstelle (PHP API) identifizieren kann wer es ist.

und die log Tabelle dient nur zur Auswertung damit man weiss wer noch nicht miteinander kommuniziert hat.
 
Ja, genau das ist auch mein Problem, weswegen ich dir leider das JOIN-Beispiel vorerst schuldig bleiben muss (vielleicht morgen)...

Dass das Query von Lime funktioniert bestätigt mich noch in meiner Verwirrung xD (nichts für ungut), weil mir das sagt, dass man eigentlich jeweils denselben user (den eingeloggten) ausschließen will, dafür aber zwei UserIDs braucht...wo ich dann mit den verteilten Keksen durcheinanderkomme, was aber auch daran liegen kann, dass ich mir die ganze Zeit soviele davon reingezerrt habe, egal, nimm dir unsere kollektive Verwirrung einfach fürs nächste DB-Design zu Herzen :).

@ übermirPost: wäre es dann nicht aufgegangen, die externen IDs genau so auch intern zu verwenden?
 
@ übermirPost: Leider nicht, dies würde Client seitig (C# Programm) Probleme bereiten... Ich brauch die ID als Primary Key für mein Vorgehen. Ist ne relativ komplexe Sache. Allerdings muss ich auch sagen, dass der DB ausschnitt nur ne example DB war und nicht der richtigen entspricht. Glaub hätten sonst das Problem in einem Jahr noch ned gelöst mit meinen Verwirrungsfähigkeiten :D
 
aaaahh jetzt hab ich das Design-Problem verstanden.

Halten wir mal fest, dass die PK-Spalte eindeutig ist.
In der tabelle log hast du ja:

id userid
1 353
1 352
2 355
2 356

Die Spalte id ist nicht eindeutig, weil 2 mal "1" und 2 mal "2" vorkommt.
So könnte man denken, dass die userid die PK-Spalte ist.
Aber das geht auch nicht, denn nach deiner Logik kann die 352 mit 1 und 352 mit 2 vorkommen.

Somit gibt es hier keine eindeutige Zuordnung.
Am Anfang hab ich mich an deinem Joing orientiert: log.id = user.id,
aber das geht eben nicht weil log.id (1 oder 2) mehr mals in der Tabelle "log" vorkommt.

Bevor man die SQL-Anweisung schreibt, sollte man die Tabelle daher so aufbauen:
User

id(PK) Name
351 X
352 Y
353 Z
354 A
355 B

Log

id (PK) userid(FK)
1 352
2 353
3 355
4 356
 
Das ist ebenfalls falsch BLR. ;)

Die Log-Tabelle dient nur als Verknüpfungstabelle, somit müsste er sie wenn dann so aufbauen, wobei man komplett mit userIDs hantieren sollte und nicht zwischen userID und der ID des Users (die hier zwei unterschiedliche sind) unterscheiden dürfte.

ID (PK) -- user1 -- user2

Die User-Tabelle selber sollte zwar anders gelöst werden, geht aber nicht - so wie er es beschrieben hat.

Was mir dazu noch einfällt: Macht es einen Unterschied ob User A den User B anschreibt bzw. umgekehrt, oder ist das irrelevant? Wenn es egal sein sollte, dann musst du die Abfrage noch zusätzlich invertieren.

Zum Thema Query:
Im Endeffekt funktioniert die Geschichte folgernder maßen. SQL erstellt intern zuerst eine quasi virtuelle Tabelle bzw. Liste aller Einträge aus der Log-Tabelle, die eine ID=1 besitzen. Anschließend nimmt er alle User (abgesehen von dem eingeloggten, hier 352) und vergleicht jede einzelne UserID mit allen Einträgen aus der virtuellen Log-Tabelle. Ist dort kein Eintrag mit dieser UserID vorhanden, wird die Row mit der UserID ausgegeben. Ist ein Eintrag vorhanden, wird die Row ignoriert.


Nur so als Exkurs am Rande, für die Interessierten:

Das Prinzip hab ich selber einmal verwenden müssen, allerdings hat es mich genauso viel Anstrengung gekostet darauf zu kommen, wie ihn. ^^
Meine Abfrage sieht nur noch komplexer aus, wenn ich so drüber nachdenke...
SQL:
SELECT *
	FROM intern_user
	WHERE 
	(
		id NOT IN 
		(
    		SELECT a.userID
			FROM intern_dienstplan AS a
			INNER JOIN intern_events_uucat AS b ON a.uucatID=b.id
			INNER JOIN intern_events_ucat as c ON b.ucatID=c.id
			INNER JOIN intern_events_cat AS d ON c.catID=d.id
			WHERE d.eventID='".$_POST['eventid']."'
			GROUP BY a.userID
			HAVING sum(b.wert) >= 100
		)
	)
	AND status='1'
	AND gruppe!=3
	ORDER BY name ASC

Was war hier die Schwierigkeit?
Eigentlich nur der innere Teil, da das eine Hierarchie darstellt.
Grundlegend gibt es die intern_events. Diese haben Kategorien: intern_events_cat. Diese haben dann Unterkategorien ... usw. Die Unter-Unterkategorien sind die letzte Ebene und können in den Dienstplan (reine Verknüpfungstabelle, wie deine hier: ID -- userID -- uucatID) eingetragen werden.
Das Problem an sich ist, dass nur Einträge gewollt sind, die ein bestimmtes Event haben -> bedeutet alle Tabellen verknüpfen. Zudem geben die verschiedenen Unter-Unterkategorien einen gewissen Wert an "getätigter Arbeit" (50 oder 100%), weswegen hier noch summiert werden muss.
Ich hab mir anfangs schwer getan zu begreifen, wie ich alle User auslesen kann, die keinen Eintrag in der Tabelle haben. Nur wie verknüpft man "nicht vorhandene Einträge" mit einem bestimmten Event? ^^


Gruß
 
  • Gefällt mir
Reaktionen: SP7
Zurück