SELECT über 5 Tabellen

BGrojer

Mitglied
Hi!

Ich bräuchte hilfe bei für ein etwas umfangreichers SQL STMT auf MS SQL Server.

Es gibt folgende Tabellen:
- tbl_mitarbeiter (Felder: ID, Vorname, Nachname)
- tbl_unternehmen (Felder: ID, Unternehmensname)
- tbl_gruppe (Felder: ID, Gruppenname)
- tbl_unt_ma_change (Felder: ID, Unternehmen_ID, Mitarbeiter_ID, datumVon, datumBis)
- tbl_grp_ma_change (Felder: ID, Gruppe_ID, Mitarbeiter_ID, datumVon, datumBis)

In den beiden Tabellen tbl_unt_ma_change und tbl_grp_ma_change sind im Prinzip alle änderungen der Unternehmen bzw. Gruppen erfasst.

Folgendes soll bewirkt werden: Es soll jeder Mitarbeiter nur 1 mal ausgegeben werden mit dem letzten Unternehmen und der letzten Gruppe.

lg und Danke für jede Hilfe
 
Wie sieht denn Dein bisheriger Ansatz aus?
Oder möchtest du mal eben die Lösung hingeschrieben bekommen, ohne es selbst versucht zu haben?:(
 
Versuchst schon stunden lang nur dahinter komm ich net ;(

SELECT tbl_mitarbeiter.ID, tbl_mitarbeiter.str_vorname, tbl_mitarbeiter.str_nachname, tbl_unternehmen.str_bezeichnung AS str_unternehmen,
tbl_gruppe.str_bezeichnung AS str_gruppe
FROM tbl_unternehmen INNER JOIN
tbl_ma_change_unternehmen ON tbl_unternehmen.ID = tbl_ma_change_unternehmen.int_unternehmen_ID RIGHT OUTER JOIN
tbl_gruppe INNER JOIN
tbl_ma_change_gruppe ON tbl_gruppe.ID = tbl_ma_change_gruppe.int_gruppe_ID RIGHT OUTER JOIN
tbl_mitarbeiter ON tbl_ma_change_gruppe.int_mitarbeiter_ID = tbl_mitarbeiter.ID ON
tbl_ma_change_unternehmen.int_mitarbeiter_ID = tbl_mitarbeiter.ID

Das wär ja mal mein Ansatz ...

Aber wie ich den Datensatz mit dem höchsten Datum zurückbekomme aus den Subtabellen ist mir en Rätsel ... und genauso wie ich den Mitarbeiter nur einmal zurückbekomme wenn er öfters Gruppe/Unternehmen gewechselt hat.

Danke trotzdem für die Antwort!
 
Ah! Hast ja doch schon mal überlegt. :-)
Irgendwie heißen die Tabellen aber auf einmal anders als oben...
Und die Joins scheinen zwar so zu funktionieren, sind allerdings etwas sehr komisch durcheinander geordnet...
Habe mal ein neues Statement gemacht:
PHP:
SELECT tbl_mitarbeiter.ID, tbl_mitarbeiter.str_vorname, tbl_mitarbeiter.str_nachname, tbl_unternehmen.str_bezeichnung AS str_unternehmen,tbl_gruppe.str_bezeichnung AS str_gruppe
FROM tbl_mitarbeiter

--Verbindung zur Gruppe
RIGHT OUTER JOIN tbl_unt_ma_change ON tbl_mitarbeiter.ID = tbl_unt_ma_change.int_mitarbeiter_ID
LEFT JOIN tbl_gruppe ON tbl_ma_change_gruppe.int_gruppe_ID = tbl_gruppe.ID

--Verbindung zum Unternehmen
RIGHT OUTER JOIN tbl_ma_change_unternehmen ON tbl_mitarbeiter.ID = tbl_ma_change_unternehmen.int_mitarbeiter_ID 
INNER JOIN tbl_unternehmen ON tbl_ma_change_unternehmen.int_unternehmen_ID = tbl_unternehmen.ID 

--Je Mitarbeiter nur Gruppe und Firma mit dem höchsten Beginndatum
WHERE tbl_ma_change_gruppe.datumVon=(SELECT MAX(ma_chg.datumVon) FROM tbl_ma_change_gruppe ma_chg WHERE ma_chg.int_mitarbeiter_ID=tbl_mitarbeiter.ID)
AND tbl_ma_change_unternehmen.datumVon=(SELECT MAX(unt_chg.datumVon) FROM tbl_ma_change_unternehmen unt_chg WHERE unt_chg.int_mitarbeiter_ID=tbl_mitarbeiter.ID)

Die Zeilen mit den -- vorangestellt sind Kommentarzeilen und können natürlich -wie jede Leerzeile auch- herausgenommen werden.
Wenn ich das richtig verstanden habe, sind alle Mitarbeiter mindestens einmal in den Change-Tabellen vertreten, da sie damit einem Unternehmen zugeordnet sind.
Wenn dem so ist, kannst du die beiden Right outer Joins auch zu Inner Joins machen.
So (wie ich es geschrieben habe) sollten auch Mitarbeiter ausgegeben werden, die noch nicht einem Unternehmen bzw. einer Gruppe zugehörig sind.
Sieht mir sehr nach einer Lösung für eine Zeitarbeitsfirma aus.
Was kriegste denn dafür? :-)

Ist natürlich nur schnell zusammengeschrieben und ohne Gew(a)ehr.. :-)

PS: Meine Antwort wäre übrigens wahrscheinlich nicht so ausführlich ausgefallen, wenn du unfreundlich reagiert hättest.
Mach mal hilft ein Danke. :)
 
Hey!

Okay danke für die Hilfe ; ) Funktioniert auch schon fast so wie ich das gern hätte ...
Deine STMT hat gleich funktioniert bis auf eine kleine Verwechslung der Tabellen bei der Verbindung zur Gruppe und das mein "datumVon" "date_von" heißt ...

Naja ich hab das Post von zuhause ausgemacht und die Tabellen sind @work gewesen ; ) Daher die leicht anderen Namen ; )

Hier nochmal die von mir abgeänderte Version.

PHP:
SELECT tbl_mitarbeiter.ID, tbl_mitarbeiter.str_vorname, tbl_mitarbeiter.str_nachname, tbl_unternehmen.str_bezeichnung AS str_unternehmen,tbl_gruppe.str_bezeichnung AS str_gruppe 
FROM tbl_mitarbeiter 

--Verbindung zur Gruppe 
RIGHT OUTER JOIN tbl_ma_change_gruppe ON tbl_mitarbeiter.ID = tbl_ma_change_gruppe.int_mitarbeiter_ID 
LEFT JOIN tbl_gruppe ON tbl_ma_change_gruppe.int_gruppe_ID = tbl_gruppe.ID 

--Verbindung zum Unternehmen 
RIGHT OUTER JOIN tbl_ma_change_unternehmen ON tbl_mitarbeiter.ID = tbl_ma_change_unternehmen.int_mitarbeiter_ID 
INNER JOIN tbl_unternehmen ON tbl_ma_change_unternehmen.int_unternehmen_ID = tbl_unternehmen.ID 

--Je Mitarbeiter nur Gruppe und Firma mit dem höchsten Beginndatum 
WHERE tbl_ma_change_gruppe.date_von=(SELECT MAX(ma_chg.date_von) FROM tbl_ma_change_gruppe ma_chg WHERE ma_chg.int_mitarbeiter_ID=tbl_mitarbeiter.ID) 
AND tbl_ma_change_unternehmen.date_von=(SELECT MAX(unt_chg.date_von) FROM tbl_ma_change_unternehmen unt_chg WHERE unt_chg.int_mitarbeiter_ID=tbl_mitarbeiter.ID)

Leider hab ich noch ein Problem damit! Es ist nicht so, dass jeder MItarbeiter mind. 1 mal in der Change Tabelle sein muss! Es kann auch sein, dass er weder ein Unternehmen ... und auch keine Gruppe hat. Allerdings gibts da Probleme ;-( Er wird nicht zurückgegeben.

Kannst du mir da nochmal unter die Arme greifen?

Achja ... nein es ist nicht für eine Zeitarbeitsfirma : D ... Und bekommen ... naja ... Dient nur zur Beschleunigung des bei uns im Moment aktull eingesetzten Intranet. (im Moment mehrere Subabfragen die einzeln ausgeführt werden)

lg und nochmal Danke ;)
 
Hmmm, da muss ich auch erst mal überlegen...
Bei einem (Right) Outer Join werden jeder linke Datensatz mit alle passenden rechten Datensätzen kombiniert (wie bei inner Join) und zusätzlich bei allen linken Datensätzen, die keine Verknüpfung auf der rechten Seite aufweisen, eine Zeile, auf der rechten Seite mit NULL-Werten gefüllt, zurückgegeben.
Das heißt also, dass nur in diesem Falle auf der rechten Seite Null-Werte stehen dürften (es sei denn, du hast NULL-fähige Spalten, dann wäre das aber zumindest bei dem PK der Fall).
Aus dieser Überlegung dürfte es genügen, wenn du den WHERE-Teil so erweiterst:
PHP:
--Je Mitarbeiter nur Gruppe und Firma mit dem höchsten Beginndatum
WHERE (tbl_ma_change_gruppe.date_von IS NULL OR tbl_ma_change_gruppe.date_von=(SELECT MAX(ma_chg.date_von) FROM tbl_ma_change_gruppe ma_chg WHERE ma_chg.int_mitarbeiter_ID=tbl_mitarbeiter.ID))
AND (tbl_ma_change_unternehmen.date_von IS NULL OR tbl_ma_change_unternehmen.date_von=(SELECT MAX(unt_chg.date_von) FROM tbl_ma_change_unternehmen unt_chg WHERE unt_chg.int_mitarbeiter_ID=tbl_mitarbeiter.ID))
Geholfen ? :)

PS: Prozesse beschleunigen klingt nach qualifizierter Azubi-Arbeit (letztes Lehrjahr) :-)
 
Geholfen jein .., aber selbst draufgekommen (dank MS SQL Enterprise Manager)

Das Problem war bei des Joins die in die "falsche" Richtung waren.

Danke Gorcky hast mir sehr geholfen.

lg

Undying

Hier nochmal der Code (working) falls es wem interessiert ; )

PHP:
SELECT     tbl_mitarbeiter.ID, tbl_mitarbeiter.str_vorname, tbl_mitarbeiter.str_nachname, tbl_unternehmen.str_bezeichnung AS str_unternehmen, 
                      tbl_gruppe.str_bezeichnung AS str_gruppe
FROM         tbl_ma_change_unternehmen LEFT OUTER JOIN
                      tbl_unternehmen ON tbl_ma_change_unternehmen.int_unternehmen_ID = tbl_unternehmen.ID RIGHT OUTER JOIN
                      tbl_mitarbeiter LEFT OUTER JOIN
                      tbl_gruppe RIGHT OUTER JOIN
                      tbl_ma_change_gruppe ON tbl_gruppe.ID = tbl_ma_change_gruppe.int_gruppe_ID ON tbl_mitarbeiter.ID = tbl_ma_change_gruppe.int_mitarbeiter_ID ON
                       tbl_ma_change_unternehmen.int_mitarbeiter_ID = tbl_mitarbeiter.ID
WHERE     (tbl_ma_change_gruppe.date_von IS NULL OR
                      tbl_ma_change_gruppe.date_von =
                          (SELECT     MAX(ma_chg.date_von)
                            FROM          tbl_ma_change_gruppe ma_chg
                            WHERE      ma_chg.int_mitarbeiter_ID = tbl_mitarbeiter.ID)) AND (tbl_ma_change_unternehmen.date_von IS NULL OR
                      tbl_ma_change_unternehmen.date_von =
                          (SELECT     MAX(unt_chg.date_von)
                            FROM          tbl_ma_change_unternehmen unt_chg
                            WHERE      unt_chg.int_mitarbeiter_ID = tbl_mitarbeiter.ID))
 
Zurück