Benutzer mit den meisten Antworten
Linq und Left Outer Join

Frage
-
Hallo Leute,
wie realisiere ich ein Left Outer Join mit Linq.
Hier mache ich eine normale Join-Abrage:
Dim ResultInnerJoin = From K In colK Join K2 In colK2 _ On K.ID Equals K2.ID _ Select K
Hier mein Versuch, die Abfrage so zu machen, dass ich alle Elemente von colK erhalte, die nicht in die obige Join-Ergebnismenge passen:
Dim ResultLeftOuterJoin = From K In colK Group Join K2 In colK2 _ On K.ID Equals K2.ID _ Into MyList = Group _ Select MyList
Nur leider stimmt das Ergebnis von ResultLeftOuterJoin nicht.
Was mache ich falsch? Vielen Dank im Voraus Christian
Christian Tauschek
Antworten
-
Hallo Christian,
wenn Du B nur als Filter-Kriterium verwenden willst, wäre ein (LEFT) JOIN überflüssig.
Um nur die Elemente von A zu finden, die in B nicht enthalten sind, geht zum einen Any()
Dim listeA As New List(Of Integer) From {1, 2} Dim listeB As New List(Of Integer) From {2, 3} ' SQL: SELECT a FROM listeA AS a WHERE NOT EXISTS(SELECT * FROM listeB AS b WHERE b = a) Dim q = From a In listeA Where Not listeB.Any(Function(b) b = a) Select a For Each i In q Console.WriteLine(i) Next
(was in SQL überlicherweise eine Abfrage mit NOT EXISTS oder NOT IN() wäre)
Sind beide Auflistungen vom gleichen Typ und Equals richtig eingestellt, geht es auch mittels Except:
Dim q2 = listeA.Except(listeB) For Each i In q2 Console.WriteLine(i) Next
Einen Group Join braucht man erst, wenn Werte aus beiden Auflistungen haben möchte:
' hilfsweise Cast auf Nullable anderes als 0 zu erhalten Dim q3 = From a In listeA.Cast(Of Integer?)() Group Join b In listeB.Cast(Of Integer?)() On a Equals b Into listeAB = Group From ab In listeAB.DefaultIfEmpty() Select a, ab For Each i In q3 Console.WriteLine("a = {0}, ab = {1}", i.a, If(i.ab, -1)) Next
(hier etwas gekünstelt, da nur ein Integer vorhanden ist - und auf Nullable(Of Integer) gecastet.)
Gruß Elmar
- Als Antwort markiert Christian Tauschek Samstag, 22. Februar 2014 01:52
Alle Antworten
-
Hallo Christian,
über DefaultIfEmpty, siehe Gewusst wie: Kombinieren von Daten mit LINQ mithilfe von Joins (Visual Basic)
und dort den Abschnitt Ausführen eines linken äußeren Joins mithilfe der Group Join-Klausel
Gruß Elmar
-
Hallo Elmar,
ich habe dir das Problem leider falsch geschildert.
Daher nun hoffentlich richtig:
Menge A enthält die ID 1 und 2
Menge B enthält die ID 2 und 3
Beziehung ist: A.ID = B.IDAls Ergebnis möchte ich mit LINQ nur die ID 1 erhalten.
So sollte es ohne Linq gehen:
SELECT * FROM A LEFT JOIN B ON A.ID = B.ID WHERE B.IDIS NULL
mfg
Christian
Christian Tauschek
-
Hallo Christian,
wenn Du B nur als Filter-Kriterium verwenden willst, wäre ein (LEFT) JOIN überflüssig.
Um nur die Elemente von A zu finden, die in B nicht enthalten sind, geht zum einen Any()
Dim listeA As New List(Of Integer) From {1, 2} Dim listeB As New List(Of Integer) From {2, 3} ' SQL: SELECT a FROM listeA AS a WHERE NOT EXISTS(SELECT * FROM listeB AS b WHERE b = a) Dim q = From a In listeA Where Not listeB.Any(Function(b) b = a) Select a For Each i In q Console.WriteLine(i) Next
(was in SQL überlicherweise eine Abfrage mit NOT EXISTS oder NOT IN() wäre)
Sind beide Auflistungen vom gleichen Typ und Equals richtig eingestellt, geht es auch mittels Except:
Dim q2 = listeA.Except(listeB) For Each i In q2 Console.WriteLine(i) Next
Einen Group Join braucht man erst, wenn Werte aus beiden Auflistungen haben möchte:
' hilfsweise Cast auf Nullable anderes als 0 zu erhalten Dim q3 = From a In listeA.Cast(Of Integer?)() Group Join b In listeB.Cast(Of Integer?)() On a Equals b Into listeAB = Group From ab In listeAB.DefaultIfEmpty() Select a, ab For Each i In q3 Console.WriteLine("a = {0}, ab = {1}", i.a, If(i.ab, -1)) Next
(hier etwas gekünstelt, da nur ein Integer vorhanden ist - und auf Nullable(Of Integer) gecastet.)
Gruß Elmar
- Als Antwort markiert Christian Tauschek Samstag, 22. Februar 2014 01:52
-
Hallo Elmar,
danke für deine Antwort.
Es hat nun mit Variante 1 und 3 funktioniert.
Da ich natürlich keine Integer sondern Klassen-Objekte als Auflistung verwende musste ich nur etwas anpassen.
Variante 2 ist nicht gegangen, da ich die IEquality...(Of T) nicht mehr in die Klasse implementiert habe.
(das war mir um diese Uhrzeit schon etwas zu viel.... werde ich aber sicher zu einem anderen Zeitpunkt noch nachholen)
mfg
ChristianChristian Tauschek