JOIN Problem

Saugkraft

Saugkraft

Aktives Mitglied
Thread Starter
Dabei seit
20.02.2005
Beiträge
8.998
Reaktionspunkte
3.189
Hallo Leute,

ich habe ein Problem mit einem JOIN, bzw. ich weiß nicht, ob sich das Problem mit einem JOIN lösen lässt.

Tabelle 1:
idt1
mitarbeiter_id (Kommt aus einer dritten Tabelle)
termin

Tabelle 2:
idt2
mitarbeiter_id (Kommt aus einer dritten Tabelle)
idt1 (Fremdschlüssel aus Tabelle 1)
abteilung_id


In Tabelle 1 sind folgende Einträge vorhanden.
Code:
idt1 mitarbeiter_id termin
----------------------------------
[B]1  42          14.12.2010
2  42          15.12.2010[/B]
3  66          10.12.2010
4  77          19.12.2010
usw.

In Tabelle 2 sind folgende Einträge vorhanden.

Code:
idt2 mitarbeiter_id idt1 abteilung_id
----------------------------------
1  42              9    888
[B]2  42              1    666[/B]
3  66              3    555
4  55              8    333
5  66              7    999
6  77              6    666

Fett markiert ist, was er mir zusammenfügen soll.

Nun brauche ich die Verknüpfung beider Tabellen in folgender Form:

Code:
idt1 idt2   mitarbeiter_id abteilung_id
----------------------------------------------------
1   2       42               666           
2   null    42               null

Das bedeutet, der Server soll mir ein Resultset liefern, in dem alle Felder von Tabelle 1 auftauchen und alle relevanten von Tabelle 2. Nämlich gefiltert nach Mitarbeiter 42 und abteilung_id 666.

Das Problem:
Wenn ich über die mitarbeiter_id joine und nach 42 und 666 filtere (select * from tabelle1 right join tabelle2 on tabelle2.mitarbeiter_id = tabelle1.mitarbeiter_id where mitarbeiter_id = 42 and abteilung_id = 666), dann bekomme ich zwei Zeilen, habe aber Werte doppelt wo null stehen sollte.

Code:
idt1 idt2   mitarbeiter_id abteilung_id
----------------------------------------------------
1   2       42               666           
2   [B]2[/B]      42               [B]666[/B]

Wenn ich über idt1 joine und nach 42 und 666 filtere (select * from tabelle1 right join tabelle2 on tabelle2.idt1 = tabelle1.idt1 where mitarbeiter_id = 42 and abteilung_id = 666), dann bekomme ich nur die erste Zeile.

Code:
idt1 idt2   mitarbeiter_id abteilung_id
----------------------------------------------------
1   2       42               666

Lasse ich den Filter 666 weg, erhalte ich auch die Abteilungen 888, 555, usw., filtere ich über OR, bekomme ich auch andere Mitarbeiter_ids.

Ist das lösbar? Was meint ihr?
 
Zuletzt bearbeitet:
select * from tabelle1 right join tabelle2 on tabelle2.table1_id = tabelle1.id where mitarbeiter_id = 42 and abteilung_id = 666

->

select * from tabelle1 right join tabelle2 on tabelle2.table1_id = tabelle1.id where mitarbeiter_id = 42 or abteilung_id = 666

? Oder habe ich jetzt dein Problem nicht ganz verstanden?
 
Edit: Nee, du hast recht. Aber ich hab Schwachsinn geschrieben. Ich ändere das nochmal. Moment..
 
So jetzt passt es. Die Zuordnung über die eindeutige id in Tabelle 1 hätte problemlos geklappt, na klar. Diese Eindeutigkeit gibt es aber nicht. Da hat mein Vorgänger leider nicht normalisiert. Lässt sich ohne größeren Aufwand aber leider auch nicht ändern.

Das Resultset soll also folgendes tun:
Nimm alle Einträge mit der mitarbeiter_id 42 aus Tabelle 1 und schreibe sie in das Resultset. Sofern sowohl mitarbeiter_id 42 und abteilund_id 666 in der zweiten Tabelle vorkommen, trage die abteilung_id in das entsprechende Feld ein. Wenn nicht, trage null ein.

Kriterium für den linken Teil ist also die 42. Kriterium für den rechten Teil 42 und 666.

Mein Problem ist, dass ich beide ids aus Tabelle 1 brauche, egal ob die abteilung einen Wert liefert oder nicht. Nach der muss ich aber ebenfalls filtern und kann es nicht mit OR weil ich sonst auch die mitarbeiter_id 77 im Resultset habe.
 
mir fehlt die Zeit, als Schnellschuß:

geht nicht so was mit einem Subselect, also


where id in ( select ....) ???


Du brauchst ja sowas wie ein Kreuzprodukt auf sich selbst über die id, aber mit Zusatzabhängigkeit. Also einen outer join auf sich selbst. Durch die Zusatzbedingung würde ich das in einen Subselect verpacken. Das geht eigentlich recht performant. Mag aber sein das ich das Problem in der Kürze der Zeit übersehen habe...
 
Sowas hab ich mir auch gedacht. Mit subselects hab ich aber so gar keine Erfahrungen. Zumal ich ja zuerst mitarbeiter_id und abteilung_id aus Tabelle 2 selektieren muss, dann die alle Einträge in Tabelle 1, die die 42 enthalten, um dann die id aus Tabelle 1 auszulesen.

Da steigt mein Verstand aus. :confused:

Kurz: Hast du eine Idee, wie ich das in SQL formuliere?
 
Auf welchem Element machst du überhaupt den join?

Wenn du die ID-Spalte dafür nimmst, kann ja auch nix dabei rauskommen, weil da ja z.b unter id 4 schon jeweils verschiedene Mitarbeiter stehen.
Du solltest den Join dann auch auf der Mitarbeiter_Id machen zb.

Zumindest geht es in MS SQL so, aber ich glaube, da sollten sich andere SQLs nicht unterscheiden.

Lösbar ist das, entweder mit einem Join oder einem Subselect. Geht mit beiden.
Wobei ich den Join bevorzugen würde.
 
Hatte vergessen, den SQL String zu ändern. Natürlich, ich joine über die mitarbeiter_id. Das Problem ist, dass ich dann zwar das Ergebnis bekomme, in beiden Zeilen aber die Abteilung 666 steht.

(In meiner DB hab ich in der Tabelle 2 auch noch die id von Tabelle 1. Wenn ich darüber joine kriege ich aber nur eine Zeile.)
 
Teste mal den left join.
 
Kurz: Hast du eine Idee, wie ich das in SQL formuliere?

ohne es mir konzentriert und in Ruhe durchzulesen nicht! Vielleicht finde ich nachher die Zeit. Kannst Du die Rahmenbedingungen nochmal in einem Post zusammenfassen? Wenn ich das richtig lese fliessen hier im Thread ja noch immer Details hinzu. Vielleicht kannst Du Posting #1 mal auf einen finalen Zustand bringen. Ich schau da gern bei Gelegenheit nochmal drauf. Zur Not kannst Du mir ja die Creates auch per PN schicken nd ich teste das mal hier.
 
Hab ich probiert. Left right, inner outer, alles durch.

Das Problem scheint zu sein, dass er die Tabellen sowohl über die Mitarbeiter_id als auch über die table1_id verknüpfen kann.

Das Ergebnis sieht dann so aus:

Code:
id mitarbeiter_id table1_id abteilung_id
1  42             1           666
2  42             1           666
 
So. Hab den Eröffnungspost jetzt nochmal auf den richtigen Stand gebracht. Meine Güte, ich hab schon einen Knoten im Hirn. :D

Wäre prima wenn du nochmal drüber schaust, wegus.
 
Ich mag da was noch nicht verstanden haben, aber wenn ich weiß das ich nur die mitarbeiter_id 42 brauche, wozu dient dann die Abfrage der tabelle2 ?
 
In Tabelle 1 gibt es bis zu zwei Einträge für den Mitarbeiter 42. Wenn es zwei sind, brauche ich beide Datensätze, damit ich die abarbeiten kann. Ist es nur einer, arbeite ich nur den ab. Da ich aber nicht weiß, wieviele es sind, muss ich in Tabelle 1 alle selektieren, damit ich sie per Schleife durchlaufen kann.

Nun kann es sein, dass in Tabelle 2 kein Eintrag zu Mitarbeiter 42 ist, es kann aber auch sein, dass es einer oder zwei sind.

Wenn ich nun die Datensätze aus Tabelle 1 abarbeite, prüfe ich, ob Abteilung <> null ist oder eben nicht. Wenn eine eine Abteilung hinterlegt ist, werden die Daten abgefragt und angezeigt, wenn nicht, wird nur angezeigt, dass kein Datensatz vorhanden ist.
 
select t1.*. t2.*
from tabelle1 t1
outer join tabelle2 t2 on t1.idt1=t2.idt1
where t2.abteilung is not null

würd ich jetzt behaupten.
das selectiert alles aus t1 und joint es mit t2, wobei alle Resultat aus t2 genullt werden bei denen es keinen Match gibt (outer join halt)



...aber irgendwie ist in demProblem ein Knoten drinn glaub ich...
 
Ich habe das mal bei mir nachgebaut und folgendes scheint zu funktionieren:
Code:
select t1.*, t2.*
FROM tb1 AS t1
LEFT JOIN tb2 AS t2 ON(t1.idt1=t2.idt1)
where (t2.abteilung_id IS NOT NULL OR t2.abteilung_id IS NULL) AND t1.mitarbeiter_id = 42

Zumindestens kommen die gefragten Ergebnisse raus. Ob das jetzt heißt, das die Abfrage wirklich das macht, was erwartet wird, weiß ich nicht. ;)
 
Das stimmt natürlich und man kann das dann auch weglassen.

Das hier bringt das gleiche Ergebnis. ;)

Code:
select t1.*, t2.*
FROM tb1 AS t1
LEFT JOIN tb2 AS t2 ON(t1.idt1=t2.idt1)
where t1.mitarbeiter_id = 42
 
Zurück
Oben Unten