Seite 1 von 1

Join (Inner, Left, Right)

BeitragVerfasst: Do 22. Mär 2012, 11:55
von Josef Pötzl
Hallo!

Wie gestaltet man einen Join am sinnvollsten für VBA?

Gewünschter Join-Ausdruck:
Code: Alles auswählen
From (Tab1 Left Join Tab2 ON (Tab1.F1 = Tab2.F2 AND 5 < Tab2.F3)) Left Join Tab3 on Tab1.F1 = Tab3.F2


Vorschlag:
Code: Alles auswählen

Generator.LeftJoin("Tab1", "Tab2", "F1", RelationalOperators_Equal, "F2", 5, RelationalOperators_LessThan, "F3") _
         .LeftJoin("Tab1", "Tab3", "F1", RelationalOperators.Equal, "F2").ToString



Problem:
Gewünschter Join-Ausdruck:
Code: Alles auswählen
From (Tab1 Left Join Tab2 ON (Tab1.F1 = Tab2.F2 AND "a" < Tab2.F3)) Left Join Tab3 on Tab1.F1 = Tab3.F2

=>
Code: Alles auswählen
Generator.LeftJoin("Tab1", "Tab2", "F1", RelationalOperators_Equal, "F2", "a", RelationalOperators_LessThan, "F3") _
         .LeftJoin("Tab1", "Tab3", "F1", RelationalOperators.Equal, "F2").ToString

.. wie weiß man nun, das "a" ein String und kein Feldname ist?

Lösungsansatz:
=> Für so einen Fall den Umweg über den ConditionGenerator gehen und folgendes verwenden:
Code: Alles auswählen

set field1 = FieldGenerator.Field("F1", "Tab1")
set field2 = FieldGenerator.Field("F2", "Tab2")
set field3 = FieldGenerator.Field("F3", "Tab2")
set condition = ConditionGenerator.Add(field1, RelationalOperators_Equal, field2).Add("a", RelationalOperators_LessThan, field3)
Generator.LeftJoinCondition("Tab1", "Tab2", condition) _
         .LeftJoin("Tab1", "Tab3", "F1", RelationalOperators.Equal, "F2").ToString


Dann könnte man aber vielleicht gleich alle umständlicheren Vergleiche auslagern und bei LeftJoin nur noch Equal voraussetzen. =>
Code: Alles auswählen
set field1 = FieldGenerator.Field("F1", "Tab1")
set field2 = FieldGenerator.Field("F2", "Tab2")
set field3 = FieldGenerator.Field("F3", "Tab2")
set condition = ConditionGenerator.Add(field1, RelationalOperators_Equal, field2).Add("a", RelationalOperators_LessThan, field3)
Generator.LeftJoinCondition("Tab1", "Tab2", condition) _
         .LeftJoin("Tab1", "Tab3", "F1", "F2").ToString



... oder wir nutzen eine festgelegte Sprache um eine Bedingung als String zu formatieren, zerlegen diesen String in seine Bestandteile und bauen daraus im Net-Code eine ICondition auf.
=>
Code: Alles auswählen

Generator.LeftJoin("Tab1", "Tab2", "F1 = F2", "'a' < F3") _
         .LeftJoin("Tab1", "Tab3", "F1 = F2").ToString


=> F1 wird dann zu Tab1.F1, weil es links vom Vergleichszeichen steht. Alles was rechts steht erhält als Source den Eitnrag aus dem rechten Source (2. Parameter).
Ein String wird durch '' gekennzeichnet. Ein String ohne ''-Markierung muss dann ein Feldname sein.

Nachteil (ein großer nach meinem Geschmack) dieser Variante: die Feldnamen können nur noch per String übergeben werden. Hätte ich die Felder sowieso als IField verfügbar, muss ich das im VBA-Code wieder zu einem String machen.

Weitere Ansatz:
Wir pfeiffen auf die ISqlGenerator-Rückgabe der Join-Methoden und erlauben dahinter eine Condion zu erzeugen.
Code: Alles auswählen

set field1 = FieldGenerator.Field("F1", "Tab1")
set field2 = FieldGenerator.Field("F2", "Tab2")
set field3 = FieldGenerator.Field("F3", "Tab2")
with Generator
      .LeftJoin("Tab1", "Tab2").Condition(field1, RelationalOperators_Equal, field2).Add("a", RelationalOperators_LessThan, field3)
      .LeftJoin("Tab1", "Tab3").Condition(field1, RelationalOperators_Equal, field3)
      sql = .ToString
end with


mfg
Josef

Re: Join (Inner, Left, Right)

BeitragVerfasst: Do 22. Mär 2012, 16:08
von Josef Pötzl
Die aktuell eingebaute Variante für COM sieht so aus:
Code: Alles auswählen
Generator.From("Tab1")
         .InnerJoin("Tab1", "Tab2", "F1", "F2")
         .InnerJoin("Tab1", "Tab3", "F1", "F2", RelationalOperators.Equal | RelationalOperators.GreaterThan)

=>
Code: Alles auswählen
From (Tab1 Inner Join Tab2 On (Tab1.F1 = Tab2.F2)) Inner Join Tab3 On (Tab1.F1 >= Tab3.F2)

Re: Join (Inner, Left, Right)

BeitragVerfasst: Do 22. Mär 2012, 17:23
von Sten Schmidt
Also mir gefällt das:

Code: Alles auswählen

with Generator
      .LeftJoin("Tab1", "Tab3").Condition(field1, RelationalOperators_Equal, field3)
      sql = .ToString
end with
 


Das wäre m.E. auch noch gut lesbar:

Code: Alles auswählen

Generator.LeftJoin("Tab1", "Tab3", "F1", RelationalOperators.Equal, "F2").ToString
 


Bei dem stört mich, dass der Operator hinten steht:

Code: Alles auswählen

Generator.From("Tab1")
         .InnerJoin("Tab1", "Tab3", "F1", "F2", RelationalOperators.Equal | RelationalOperators.GreaterThan)
 


Dann vllt. lieber andersrum sortieren, wenn man den Operator nicht in die Mitte bekommt:

Code: Alles auswählen

Generator.From("Tab1")
         .InnerJoin("Tab1", "F1", "Tab3", "F2", RelationalOperators.Equal | RelationalOperators.GreaterThan)
 


PS: Kann man mit COM keine "Überladungen" machen? Oder geht das nur wenn auch die Methodensignatur eine andere ist bzw. mit Default-Values?

Re: Join (Inner, Left, Right)

BeitragVerfasst: Do 22. Mär 2012, 17:51
von Josef Pötzl
Den Operator gab ich nach hinten, damit man einen Standardwert (= RelationalOperators_Equal) nutzen kann.
=> üblicher Fall mit "Inner join Feld1 = Feld2" ergibt dann:
Code: Alles auswählen
Generator.From("Tab1")
         .InnerJoin("Tab1", "Tab3", "F1", "F2")

Im Regelfall wird auf Gleichheit geprüft werden. Genau bei diesem Fall würde dann der Code relativ kurz sein.

Code: Alles auswählen

Generator.From("Tab1")
         .InnerJoin("Tab1", "F1", "Tab3", "F2")

Damit könnte ich mich auch anfreunden.

Noch etwas könnte ich mir vorstellen:
Code: Alles auswählen
Generator.From("Tab1")
         .InnerJoin("Tab3", "F2", "F1", optional "TabX")

TabX wäre nur dann notwendig, wenn die 2. Quelle von der Quelle des vorigen FromStatements abweicht.

Gekürzt würde das so aussehen:
Code: Alles auswählen
Generator.From("Tab1")
         .InnerJoin("Tab3", "F2", "F1")

=>
Code: Alles auswählen
From Tab1 Inner Join Tab3 On Tab3.F2 = Tab1.F1



Kann man mit COM keine "Überladungen" machen? Oder geht das nur wenn auch die Methodensignatur eine andere ist bzw. mit Default-Values?

Nein, COM kennt keine Überladung. Das einzige Hilfsmittel, das man nutzen kann, ist Variant-Typen zu verwenden und dann in der Methode prüfen, welche Variante passt.

mfg
Josef