[MySQL] Kompliziertere Abfrage über 2 Wege - wie realisieren ?

crazymischl

Erfahrenes Mitglied
Hallo,
meine Tabelle sieht zur Zeit so aus: (Link zum Bild)

Zur Erklärung:
Ein Mitarbeiter leitet einen Kurs, welcher an einem Kurstag (Wochentag) stattfindet.
Der Kunde besucht die Kurse. Manche Kunden haben Mitarbeiter als direkte Ansprechpartner, aber nicht alle.

Nun werden Fehlzeiten erstellt, in denen der Kunde nicht da war. Die kann über die direkte Auswahl des Kurses (Kid, Uid bleibt dann null) geschehen, oder über einen Kurstag (Uid, Kid ist dann null).
Bedeutet: Variante a) Kunde1 war nicht in Kurs1
Variante b) Kunde1 war am Montag (=Uid) nicht da, Kurs1 findet Montags(=Uid) statt

Nun muss ich alle Fehlzeiten, die einen Mitarbeiter betreffen, abfragen.
Bedeutet: Ich muss
  • alle kurse auslesen und dazu die Fehlzeiten
  • alle kurse, für jeden Kurs alle besucher, dann die Fehlzeiten der Besucher (aber nur die Fehlzeiten, welche als Uid eine mit dem Kurs verknüpfte Uid haben (in Kurstage muss Kid und Uid verknüpft sein))

Variante 1:
Code:
Select
  fehlzeit.fid,
  fehlzeit.sid,
  fehlzeit.kid,
  fehlzeit.uid,
  fehlzeit.fgrund
From
  fehlzeit Inner Join
  kurse On kurse.kid = fehlzeit.kid Inner Join
  mitarbeiter On mitarbeiter.lid = kurse.lid
Variante 2:
Code:
Select
  fehlzeit.fid,
  fehlzeit.sid,
  fehlzeit.kid,
  fehlzeit.uid,
  fehlzeit.fgrund
From
  besucht Inner Join
  kunden On kunden.sid = besucht.sid Inner Join
  kurse On besucht.kid = kurse.kid Inner Join
  kurstage On kurse.kid = kurstage.kid Inner Join
  fehlzeit On kurstage.uid = fehlzeit.uid And kunden.sid = fehlzeit.sid
  Inner Join
  mitarbeiter On mitarbeiter.lid = kurse.lid

So bekomme ich beides einzeln hin.
Meine Frage: Wie kann ich diese Abfragen kombinieren ?
Leider verzweifle ich daran :(
Danke schonmal für eure Vorschläge !
 

Anhänge

  • Unbenannt.jpg
    Unbenannt.jpg
    112,6 KB · Aufrufe: 15
Zuletzt bearbeitet:
UNION ist eine Lösung
SQL:
Select
  fehlzeit.fid,
  fehlzeit.sid,
  fehlzeit.kid,
  fehlzeit.uid,
  fehlzeit.fgrund
From
  besucht Inner Join
  kunden On kunden.sid = besucht.sid Inner Join
  kurse On besucht.kid = kurse.kid Inner Join
  kurstage On kurse.kid = kurstage.kid Inner Join
  fehlzeit On kurstage.uid = fehlzeit.uid And kunden.sid = fehlzeit.sid
  Inner Join
  mitarbeiter On mitarbeiter.lid = kurse.lid
UNION Select
  fehlzeit.fid,
  fehlzeit.sid,
  fehlzeit.kid,
  fehlzeit.uid,
  fehlzeit.fgrund
From
  fehlzeit Inner Join
  kurse On kurse.kid = fehlzeit.kid Inner Join
  mitarbeiter On mitarbeiter.lid = kurse.lid
 
Zuletzt bearbeitet von einem Moderator:
Hi,
ersteinmal Danke für deine Antwort.
Die Abfragen per Union zu verbinden habe ich auch schon gemacht, funktioniert auch.

Allerdings bin ich dabei die Syntax mit Joins zu lernen, daher ist die kombination mit Union natürlich nicht wirklich befriedigend ;) Es geht also mehr ums Prinzip und die Verwendung mit Joins, als um die konkrete Umsetzung.

Daher würde mich prinzipiell interessieren, wie man dies mit Joins lösen kann oder ob das so nur per Union machbar ist.

Trotzdem Danke schonmal ;)
 
Da die 2 Quellen sich ergänzen brauchst du so oder so irgenwo da drin ein UNION

UNION = Mengen vergrössern (Betrifft die Anzahl Zeilen)
JOIN = Mengen kombinieren (Betrifft die Anzahl Spalten).

Soviel zum normalen.

Da du aber beides mal die gleiche Quelle (Fehlzeiten) hast, sollte es auch mit LEFT JOINS gehen.

Ich habe mal deine 2 SQLs analysiert und verstehe nicht ganz:
Variante 1: Wozu brauchst du da die Mitarbeitertabelle?

Variante 2: Wozu brauchst du die Tabelle besucht?

Grundsätzlich machst du viel zu viele umwege. Wenn der Kurs nicht besucht wird, kannst du direkt von fehlzeit.kid auf die Kurstage mit derselben kid zugreiffen und hast gleich alle Kurstage daraus die nicht besucht sind.
Um eine saubere Ausgabe hinzukriegen solltest du im SELECT-Teil die uid un kid aus der Tabelle Kurstage übernehmen, damit sie nicht mehr NULL beinhalten.

Das folgende ist ungetestet, könnte aber funktionieren
SQL:
SELECT
  fehlzeit.fid,
  fehlzeit.sid,
  kurstage.kid,
  kurstage.uid,
  fehlzeit.fgrund
FROM
	fehlzeit
	INNER JOIN kurstage
	    #IFNULL() verwende ich, damit kein Fehler beim Vergleich mit NULL auftauechen kann
		ON (kurstage.uid  = IFNULL(fehlzeit.uid, false)
			OR kurstage.kid  = IFNULL(fehlzeit.kid, false))
 
Zuletzt bearbeitet von einem Moderator:
Hi,
Vielleicht ein wenig zur Erklärung:
Es finden täglich verschiedene Kurse, geleitet von verschiedenen Mitarbeitern statt.
Ein Kunde besucht mehrere Kurse täglich.

Wenn ein Kunde nicht da ist, schreibt er entweder für die entsprechenden Kurse die Fehlzeit, oder er sagt ich war "Donnerstag" nicht da.

Die Fehlzeiten sollen nun aus der Sicht des Mitarbeiters ausgelesen werden.
D.h. Mitarbeiter mit ID 1 meldet sich an.
Nun werden zum Mitarbeiter alle Kurse ausgelesen.
Für jeden Kurs müssen nun
a) alle Fehlzeiten die direkt für den Kurs geschrieben sind abgefragt werden
b) alle Kunden, die den Kurs besuchen, abgefragt werden, dann für jeden Kunden die Fehlzeiten bei welchen eine Uid eingetragen ist, welche in Kurstage mit Kid verknüpft ist.

Beispiel:
Kurs 1 findet Donnerstag & Freitag statt. (Kurstage: 2 Einträge: Kurs 1 (Kid)- Donnerstag bzw. Freitag (Uid))
Kunde 1,2 besuchen Kurs 1 (Tabelle besucht: 2 Einträge), Kunde 3 besucht einen anderen Kurs 2
Kunde 1 schreibt Fehlzeit Fid=1 für den Kurs (Fehlzeiten: Sid = Kunde 1, Kid= Kurs1, Uid=null)
Kunde 2 schreibt Fehlzeit Fid=2 für Donnerstag (Fehlzeiten: Sid= Kunde2, Kid=null, Uid= Donnerstag)
Kunde 3 schreibt Fehlzeit Fid=3 für Donnerstag(Fehlzeiten: Sid= Kunde3, Kid=null, Uid= Donnerstag)


Jetzt soll die Abfrage
a) Alle Fehlzeiten mit Kid = Kurs 1
b) Alle Kunden, die Kurs1 besuchen (-> Kunde 1 und Kunde 2)
Dann für jeden dieser Kunden, die Kurs 1 besuchen, die Fehlzeit finden, welche als Uid = Donnerstag haben

Bedeutet:
Fehlzeit 1 wird gefunden, da Kid= Kurs1 passt.
Fehlzeit 2 wird gefunden, weil Kunde1+Kurs1 in besucht(Kunde 2 (Sid) - Kurs 1 (Kid)) verknüpft sind und Donnerstag+Kurs1 Kurstag(Kurs1 (Kid) - Donnerstag (Uid)) verknüpft sind.
Fehlzeit 3 wird ignoriert, da Kunde3 keinen Kurs von Mitarbeiter 1 besucht.

Was also gegeben ist, ist die Mitarbeiter- ID.
Von dieser ausgehend sollen also alle Fehlzeiten, welche für den Mitarbeiter relevant sind, aufgelistet werden.

PS: dein oberes Statement funktioniert leider nicht, beim Ausführen werden Fehlzeiten für einzelne Stunden 3x aufgelistet.

Mfg.
 
Zuletzt bearbeitet:
So auf die schnelle:
SQL:
SELECT DISTINCT
	kurse.lid,
	besucht.sid,
	fehlkurstage.kid,
	fehlkurstage.uid
FROM
	(
		SELECT DISTINCT
		  	kurstage.kid,
		 	kurstage.uid,
		 	fehlzeit.sid
		FROM
		    fehlzeit
		    INNER JOIN kurstage
		        ON (kurstage.uid  = IFNULL(fehlzeit.uid, false)
		            OR kurstage.kid  = IFNULL(fehlzeit.kid, false))
	) AS fehlkurstage
	INNER JOIN kurse
		ON kurse.kid = fehlkurstage.kid
	INNER JOIN besucht
		ON fehlkurstage.kid = besucht.kid
			AND fehlkurstage.sid = besucht.sid

Im innern SQL selektioniere ich alle fehltage
SQL:
--fehlkurstage
		SELECT DISTINCT
		  	kurstage.kid,
		 	kurstage.uid,
		 	fehlzeit.sid
		FROM
		    fehlzeit
		    INNER JOIN kurstage
		        ON (kurstage.uid  = IFNULL(fehlzeit.uid, false)
		            OR kurstage.kid  = IFNULL(fehlzeit.kid, false))

Diese verbinde ich dann mit den kursen und den Benutzern
SQL:
SELECT DISTINCT
	kurse.lid,
	besucht.sid,
	fehlkurstage.kid,
	fehlkurstage.uid
FROM
	(
		[:fehlkurstage:]
	) AS fehlkurstage
	INNER JOIN kurse
		ON kurse.kid = fehlkurstage.kid
	INNER JOIN besucht
		ON fehlkurstage.kid = besucht.kid
			AND fehlkurstage.sid = besucht.sid

Somit habe ich alle Ids zusammen die ich brauche.
 
Zuletzt bearbeitet von einem Moderator:
Zurück