Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Frage zu JOIN (https://www.delphipraxis.net/191540-frage-zu-join.html)

harfes 26. Jan 2017 07:11

Datenbank: Firebird • Version: 2.1 • Zugriff über: Delphi/IBDAC

Frage zu JOIN
 
Hallo,

ich habe folgende Abfrage:

with DM1.DataModule1.IBCArtikelQuery do
begin
Close;
SQL.Clear;
SQL.Add('select A.*,E.EINHEIT,W.WARENGRUPPE,L.FIRMA,L.KREDITORENNR ');
SQL.Add('from ARTIKEL A ');
SQL.Add('left outer join EINHEITDB E on A.VERPEINHEIT=E.EID ');
SQL.Add('left outer join EINHEITDB E on A.VERBRAUEINHEIT=E.EID ');
SQL.Add('left outer join EINHEITDB E on A.LAGBESTEINHEIT=E.EID ');
SQL.Add('left outer join EINHEITDB E on A.MINBESTEINHEIT=E.EID ');
SQL.Add('left outer join WARENGRUPPEDB W on A.WARENGRUPPE=W.WID ');
SQL.Add('left outer join LIEFERANT L on A.LIEFERANT1=L.LID ');
ExecSQL;
end;

Diese meldet bei der zweiten (und natürlich den folgenden) "left outer join" folgenden Fehler: "Alias E conflicts with an alias in the same statement". Ok...soweit klar, woher der Fehler kommt. Eine Lösung ist, das E in den weiteren statements durch andere Buchstaben zu ersetzen - aber irgendwie nicht sonderlich elegant.
Hat jemand noch eine andere ("elegantere") Lösung? Insbesondere in Hinsicht auf eine mögliche, zukünftige "Vermehrung" der Einheiten-Felder, wird es irgendwann unübersichtlich...

Hartmut

MrSpock 26. Jan 2017 07:34

AW: Frage zu JOIN
 
Wenn du mehrfach einen Join mit einer Tabelle machen möchtest, musst du jedes mal einen anderen Alias benutzen.

DeddyH 26. Jan 2017 07:37

AW: Frage zu JOIN
 
Ich nummeriere die Aliase nötigenfalls durch, wenn ich dieselbe Tabelle mehrfach hinzujoine (E1, E2, E3 usw.). Aber könnte man in Deinem Fall die Verknüpfungsbedingungen nicht einfach verodern?
SQL-Code:
left outer join EINHEITDB E on A.VERPEINHEIT=E.EID OR A.VERBRAUEINHEIT=E.EID OR A.LAGBESTEINHEIT=E.EID OR A.MINBESTEINHEIT=E.EID

TBx 26. Jan 2017 07:46

AW: Frage zu JOIN
 
Die Frage ist, was willst Du mit dieser Abfrage erreichen?
Zu jedem Artikel so vorhanden die/den Lieferanten, die Warengruppe(n) ausgeben, soweit so klar.
Aber was soll bei den Einheiten passieren? Auf welche Einheit soll sich Dein E.Einheit beziehen?
Formuliere bitte einmal in Worten, was Du erreichen möchtest und was Dir gegeben ist. Dann läßt sich sicherlich eine mehr oder minder elegante Lösung finden.

jobo 26. Jan 2017 09:38

AW: Frage zu JOIN
 
Zitat:

Zitat von harfes (Beitrag 1359988)
.. - aber irgendwie nicht sonderlich elegant.
Hat jemand noch eine andere ("elegantere") Lösung? Insbesondere in Hinsicht auf eine mögliche, zukünftige "Vermehrung" der Einheiten-Felder, wird es irgendwann unübersichtlich...

Wie bereits geschrieben wurde:
Es gibt keine andere Lösung, jeder Alias (sowohl einer Tabelle, als auch eines Feldes) muss eindeutig benannt sein. Es ergibt auch sonst keinen Sinn. Und damit zu Deinem Statement. Stellt man sich vor, in Deinem Statement stünden eindeutige Aliase, was würde es dann für einen Sinn ergeben?
Vielleicht ist Dir die Join-Thematik nicht richtig klar? Oder Du hast ein unglückliches Datenmodell vorliegen?

Aliasnamen
Wenn ich Tabellen mehrfach einbinde, wähle ich den Alias ("entgegen" des Tabellennamens) so, dass er die Menge beschreibt, die ich dort aufbaue bzw. abgreifen will. Dabei stelle ich u.U. auch den praktischen Nutzen eines möglichst kurzen Alias hinten an.

rokli 26. Jan 2017 09:50

AW: Frage zu JOIN
 
Hallo,

vielleicht ist es eine gute Idee, das SQL Statement erst einmal im Management Studio der DB aufzubauen, zu testen und wenn alles korrekt ist, das Ding dann nach Delphi zu bringen!

Gruß

harfes 26. Jan 2017 09:59

AW: Frage zu JOIN
 
Zunächst mal danke für eure Ideen/Anregungen. Wie ich bereits geschrieben habe, ist ein jeweils anderer Alias möglich...aber aus meiner Sicht unschön - und wenn's mehr Einheiten-Felder werden, auch irgendwann mal unübersichtlich.

Um nochmal zu verdeutlichen, warum ich das so mache: in der ARTIKEL-Tabelle habe ich verschiedene Angaben (Anzahl im Lager, Mindestanzahl, Anzahl je Bestelleinheit, etc.), die jeweils mit einer Zahl in einem Feld und mit der zugehörigen Einheit (also Stück, Karton, Rolle, etc.) bzw der ID in einem anderen Feld aus der EINHEITEN-Tabelle (das ist dann der EID) hinterlegt werden. Um beim Anzeigen nicht die ID der Einheit sondern die Einheit im Klartext anzuzeigen, muss ich dass natürlich für jedes Feld auslesen und zuordnen.
Also: ja es geht mit verschiedenen Alias (so habe ich das aktuell auch gelöst), aber ich habe mich eben gefragt, ob es nicht eine elegantere/einfachere/bessere Lösung gibt?

Hartmut

Jumpy 26. Jan 2017 10:25

AW: Frage zu JOIN
 
Irgendwie wird aber dann doch nicht klar, wenn du die so ggf. ermittelte Einheit nur 1x anzeigst, zu welcher Menge aus den Artikel sie gehört (Lagermenge, Mindestanzahl usw).
Hinzu kommt, dass so ein Artikel mehrfach angezeigt wird, wenn er in mehreren Spalten mit der Einheiten-Tabelle gejoined wird un in mehreren Spalten auch Einträge hat.

So bekäme man nur 1 Datensatz pro Artikel
SQL.Add('select A.*,E1.EINHEIT as Verpackungseinheit,E2.Einheit as Verbrauchseinheit,');//...
SQL.Add('W.WARENGRUPPE,L.FIRMA,L.KREDITORENNR');
SQL.Add('from ARTIKEL A ');
SQL.Add('left outer join EINHEITDB E on A.VERPEINHEIT=E.EID ');
SQL.Add('left outer join EINHEITDB E on A.VERBRAUEINHEIT=E.EID ');

jobo 26. Jan 2017 11:04

AW: Frage zu JOIN
 
Zitat:

Zitat von Jumpy (Beitrag 1360018)
Irgendwie wird aber dann doch nicht klar, wenn du die so ggf. ermittelte Einheit nur 1x anzeigst

Genau, daher meine Frage zum Sinn/Verständnis dieses Falles.

Und nochmal, solange mehrfach auf die Einheit referenziert wird, gibt es keine andere Möglichkeit. Zumindest nicht in dieser Darstellungsform. Erst wenn man die Artikel Attribute (alle Einheitsangaben und sonstige) transformiert und in Listenform ausgibt, könnte man mit einem Join verschiedene Einheiten reinjoinen.

Die Transformation der Artikelattribute ist aber dann auch schon ein großer Anlauf. Das wäre ggF. sinnvoll, wenn man es -jenachdem - mit sehr unterschiedlichen Artikeln zu tun hat und deren Attribute standardmäßig als separate Tabelle modelliert.
Ich glaube in diversen Webshops wird das gern mal so gemacht.
Das hat aber wieder eine Gegenindikation, bei der Suche nach Artikeln über verschiedene Attribute.

p80286 26. Jan 2017 11:49

AW: Frage zu JOIN
 
ich lehn mich mal weit aus dem Fenster:
SQL-Code:
select A.*,E.EINHEIT,W.WARENGRUPPE,L.FIRMA,L.KREDITORENNR
from ARTIKEL A
  left outer join EINHEITDB E on A.VERPEINHEIT=E.EID
  left outer join EINHEITDB E on A.VERBRAUEINHEIT=E.EID
  left outer join EINHEITDB E on A.LAGBESTEINHEIT=E.EID
  left outer join EINHEITDB E on A.MINBESTEINHEIT=E.EID
  left outer join WARENGRUPPEDB W on A.WARENGRUPPE=W.WID
  left outer join LIEFERANT L on A.LIEFERANT1=L.LID
das soll bedeuten, gib die gerade aktuelle Mengeneinheit aus (bei Ballen ist Stk null usw.)
Richtig geraten?

Gruß
K-H

jobo 26. Jan 2017 13:45

AW: Frage zu JOIN
 
Zitat:

Zitat von p80286 (Beitrag 1360028)
das soll bedeuten, gib die gerade aktuelle Mengeneinheit aus (bei Ballen ist Stk null usw.)
Richtig geraten?

Ich glaube nicht.
Die aufgeführten Einheiten sind alle unterschiedlicher Art, also meinetwegen Minbesteinheit = Paletten.
Bedeutet man kann nur palletenweise bestellen.
Lagerbesteinheit = Stück

usw...

p80286 26. Jan 2017 14:51

AW: Frage zu JOIN
 
war ein Vorschlag, jetzt sollte sich vllt. der TE äußern.
(ich hatte heute eine Recherchenanfrage von zwei Stellen beide haben laut genickt bei der schriftlichen Formulierung. Dann hab ich nachgefragt ob denn auch das gemeint sei, A:Ja B:Nein :twisted:)

Gruß
K-H

harfes 27. Jan 2017 07:42

AW: Frage zu JOIN
 
Ja, jedes Feld, zu der eine Einheit gehört, kann eine andere Einheit haben (Verpackungseinheit=1 Karton, Verbrauchseinheit=1 Stück, etc.) - daher muss ich die Einheit immer wieder abfragen. Meine (unelegante, aber funktionierende) Lösung:
Delphi-Quellcode:
with DM1.DataModule1.IBCArtQuery do
    begin
        Close;
        SQL.Clear;
        SQL.Add('select A.*,E.EINHEIT as EE,F.EINHEIT as EF,G.EINHEIT as EG,H.EINHEIT as EH,W.WARENGRUPPE as WG,L.FIRMA,L.KREDITORENNR,Z.BEZEICHNUNG as LP ');
        SQL.Add('from ARTIKEL A ');
        SQL.Add('left outer join EINHEITDB E on A.VERPEINHEIT=E.EID ');
        SQL.Add('left outer join EINHEITDB F on A.VERBRAUEINHEIT=F.EID ');
        SQL.Add('left outer join EINHEITDB G on A.LAGBESTEINHEIT=G.EID ');
        SQL.Add('left outer join EINHEITDB H on A.MINBESTEINHEIT=H.EID ');
        SQL.Add('left outer join WARENGRUPPEDB W on A.WARENGRUPPE=W.WID ');
        SQL.Add('left outer join LIEFERANT L on A.LIEFERANT1=L.LID ');
        SQL.Add('left outer join LAGERPLATZ Z on A.LAGERPLATZID=Z.LPID ');
        ExecSQL;
    end;
Nochmal: mir ging es darum, eine elegantere Abfrage zu generieren...aber offensichtlich muss das wohl so gehen (und tut es ja auch!). Danke für euren Input!!!

Hartmut

p80286 27. Jan 2017 19:04

AW: Frage zu JOIN
 
Wie wäre es denn hiermit:
SQL-Code:
select A.*,E.EINHEIT,W.WARENGRUPPE as WG,L.FIRMA,L.KREDITORENNR,Z.BEZEICHNUNG as LP
from ARTIKEL A
     left outer join WARENGRUPPEDB W on A.WARENGRUPPE=W.WID
     left outer join LIEFERANT L on A.LIEFERANT1=L.LID
     left outer join LAGERPLATZ Z on A.LAGERPLATZID=Z.LPID
     left outer join EINHEITDB E on A.VERPEINHEIT=E.EID
union
select A.*,F.EINHEIT ,W.WARENGRUPPE as WG,L.FIRMA,L.KREDITORENNR,Z.BEZEICHNUNG as LP
from ARTIKEL A
     left outer join WARENGRUPPEDB W on A.WARENGRUPPE=W.WID
     left outer join LIEFERANT L on A.LIEFERANT1=L.LID
     left outer join LAGERPLATZ Z on A.LAGERPLATZID=Z.LPID
     left outer join EINHEITDB F on A.VERBRAUEINHEIT=F.EID
union
select A.*,G.EINHEIT,W.WARENGRUPPE as WG,L.FIRMA,L.KREDITORENNR,Z.BEZEICHNUNG as LP
from ARTIKEL A
     left outer join WARENGRUPPEDB W on A.WARENGRUPPE=W.WID
     left outer join LIEFERANT L on A.LIEFERANT1=L.LID
     left outer join LAGERPLATZ Z on A.LAGERPLATZID=Z.LPID
     left outer join EINHEITDB G on A.LAGBESTEINHEIT=G.EID
union
select A.*,H.EINHEIT,W.WARENGRUPPE as WG,L.FIRMA,L.KREDITORENNR,Z.BEZEICHNUNG as LP
from ARTIKEL A
     left outer join WARENGRUPPEDB W on A.WARENGRUPPE=W.WID
     left outer join LIEFERANT L on A.LIEFERANT1=L.LID
     left outer join LAGERPLATZ Z on A.LAGERPLATZID=Z.LPID
     left outer join EINHEITDB H on A.MINBESTEINHEIT=H.EID
Gruß
K-H


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:29 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz