Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Verständnisfrage zu LEFT JOIN (https://www.delphipraxis.net/208193-verstaendnisfrage-zu-left-join.html)

Der schöne Günther 23. Jun 2021 09:27

Datenbank: Sqlite • Version: 3 • Zugriff über: FireDAC

Verständnisfrage zu LEFT JOIN
 
Liste der Anhänge anzeigen (Anzahl: 3)
Ich stehe völlig auf dem Schlauch weshalb ein LEFT JOIN in Internet-Beispielen so funktioniert wie er soll, mit meinen Test-Daten allerdings nicht. Ich versuche es so kurz wie möglich zu machen.

Das sind meine zwei Mini-Tabellen:
Anhang 54107
Code:
CREATE TABLE items (
   id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
   someValue INTEGER
);

CREATE TABLE descriptions(
   id INTEGER NOT NULL,
   lang TEXT NOT NULL,
   description TEXT,
   CONSTRAINT descriptions_pk PRIMARY KEY (id, lang),
   CONSTRAINT descriptions_FK FOREIGN KEY(id) REFERENCES items(id) ON DELETE CASCADE   
);
Jetzt füllen wir sie noch mit ganz wenigen Daten:
Code:
INSERT INTO items VALUES
   (NULL, 42),
   (NULL, 4711),
   (NULL, 1234);
   
INSERT INTO descriptions VALUES
   (1, "DEU", "Die Antwort auf alles"),
   (1, "ENG", "The answer to everything"),
   (2, "DEU", "Eine gewöhnliche Zahl"),
-- (2, "ENG", "An ordinary number"),
   (3, "DEU", "Einfach zu tippen"),
   (3, "ENG", "Easy to type");
Wir sehen hier, dass ich für "item 2" die Sprache "ENG" weggelassen habe:
Anhang 54108


Jetzt hätte ich doch gedacht, dass ich mit einem LEFT OUTER JOIN eine Trefferliste eine evtl. fehlende Sprache mit NULL aufgefüllt wird.
Code:
SELECT * FROM items LEFT OUTER JOIN descriptions USING(id);
Ergebnis:
idsomeValuelangdescription
142DEUDie Antwort auf alles
142ENGThe answer to everything
24711DEUEine gewöhnliche Zahl
31234DEUEinfach zu tippen
31234ENGEasy to type

Ich hätte noch eine Weitere Zeile mit
idsomeValuelangdescription
24711NULLNULL
oder so erwartet.

So macht es keinen Unterschied, ob ich einfach nur JOIN oder LEFT (OUTER) JOIN sage.


Was mache ich anders als das Beispiel unter
https://www.w3resource.com/sqlite/sqlite-left-join.php?
Anhang 54109
Wenn ich das Beispiel bei mir nachstelle funktioniert es auch! Der einzige Unterschied ist vielleicht mein zusammengesetzter Primärschlüssel (id, lang) in "descriptions"?

Uwe Raabe 23. Jun 2021 09:54

AW: Verständnisfrage zu LEFT JOIN
 
Wenn du immer eine vollständige Liste der Sprachen haben willst, brauchst du erstmal eine Tabelle mit allen Sprachen im Feld lang, auf der du dann den LEFT JOIN loslassen kannst. Woher sollte das System denn auch sonst wissen, welche Sprachen vorkommen können.

SQL-Code:
SELECT * FROM items
LEFT JOIN language USING(lang);
LEFT JOIN descriptions USING(id);

Der schöne Günther 23. Jun 2021 10:05

AW: Verständnisfrage zu LEFT JOIN
 
Nein, ich wollte keine Übersicht über "alles", sondern in der Query natürlich noch nach Sprache filtern.

Wenn beispielsweise für die Sprache "ENG" kein Text vorliegt, hätte ich in der Ergebnismenge gerne NULL in der Spalte "description" gehabt.

Aktuell muss ich für jedes item in der Tabelle descriptions einen Eintrag für jede Sprache anlegen und das Feld description auf NULL setzen.
Ich hätte gedacht dass man da drum herum kommt?

Uwe Raabe 23. Jun 2021 10:15

AW: Verständnisfrage zu LEFT JOIN
 
Wie schon gesagt:
Zitat:

Zitat von Uwe Raabe (Beitrag 1491424)
Woher sollte das System denn auch sonst wissen, welche Sprachen vorkommen können.

Angenommen du nimmst nur DEU-Einträge in die descriptions auf, woher sollen denn dann die NULL-Einträge für ENG kommen?

Der LEFT JOIN zwischen items und descriptions bedeutet doch nur: Gib mir alle Einträge aus items und füge die passenden Felder aus descriptions dazu, wenn es welche gibt.

Der schöne Günther 23. Jun 2021 10:29

AW: Verständnisfrage zu LEFT JOIN
 
Vielen Dank, durch deine Beharrlich hast du mich glaube ich auf die richtige Spur gebracht.
Ja, ich brauche definitv eine Tabelle mit allen Sprachen drin. Vielleicht kann man das auch mit einer Query realisieren ("Select distinct" oder sowas).

Ich denke die vollständige Query ist
Code:
SELECT * FROM items CROSS JOIN language
LEFT JOIN descriptions USING(lang, id)
Damit erhalte ich was ich brauche:
idsomeValuelangdescription
142DEUDie Antwort auf alles
142ENGThe answer to everything
24711DEUEine gewöhnliche Zahl
24711ENG 
31234DEUEinfach zu tippenn
31234ENGEasy to type
4666DEU 
4666ENGThe number of the beast

Im letzten Schritt kann ich das dann natürlich noch mit einem WHERE filtern, für die Sprache die ich brauche.

Dankesehr.

DeddyH 23. Jun 2021 11:29

AW: Verständnisfrage zu LEFT JOIN
 
3. Normalform ;)

Der schöne Günther 23. Jun 2021 22:33

AW: Verständnisfrage zu LEFT JOIN
 
Ich hatte einen harten Tag, hilf mir nochmal 😫

Was wolltest du mit der 3NF sagen? Die ist doch gegeben? Ich hätte gesagt 2NF ist sie, denn "description" ist definitiv vom gesamten Primärschlüssel abhängig. 3NF ist auch gegeben, denn von Nicht-Schlüssel-Gedöns (items.someValue und descriptions.description) ist gar nichts abhängig.

DeddyH 24. Jun 2021 05:43

AW: Verständnisfrage zu LEFT JOIN
 
Ohne die Language-Tabelle war die 3.NF eben nicht gegeben.

Blup 25. Jun 2021 16:29

AW: Verständnisfrage zu LEFT JOIN
 
Für eine konkrete Sprache sollte die Abfrage auch ohne die 3.Tabelle funktionieren:
Code:
SELECT   *
FROM     items a
LEFT JOIN descriptions b on (b.id = a.id) and (b.lang = :lang)
WHERE    (b.id is null)
Ob der Syntax für diese SQL-Datenbank passt, weis ich allerdings nicht.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:10 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