Datenbank - multilanguage - fallback
johanoa
- datenbank
0 Frank (no reg)0 André Laugks0 Frank (no reg)0 Ilja
0 André Laugks
Abend,
ich habe zwei Tabellen, in der einen steht an Stelle des Produktnamens (und anderen Spalten) nur eine Id.
Diese Id ist in der Sprach-Werte-Tabelle zu finden. Normalerweise sollte jede Id mit jeder Sprache als Zeile vorhanden sein. Dann wird über Id und Sprache der Wert ausgelesen.
Jedoch kann ich nicht sicherstellen, dass wirklich alle Sprachen (schon) existieren.
Also müsste ich meine gejointe Select-abfrage dahingegeb anpassen, dass er joint und die Sprache berücksichtigt, sollte diese aber nicht existieren soll die Standardsprache genommen werden. Wie kann ich soetwas realisieren?
id / lang / text
1 / de / Deutsch
1 / en / English
2 / de / Hallo
SELECT multilang.text
FROM multilang
INNER JOIN products
ON p.name = multilang.id
AND multilang.lang = SPRACHE
Hole ich id 1 auf English ist dies ja kein Problem. Bei id 2 hingegen schon. Hier soll er mir einfach de ausliefern.
Wie kann ich das bewerkstelligen?
Gruß
Hi,
Wie kann ich das bewerkstelligen?
Mit doppelten LEFT JOIN auf multilang, 1x für die gewünschte Sprache und einmal für die "FALLBACK" Sprache sowie mit der COALESCE() Funktion.
Ciao, Frank
Hallo!
Mit doppelten LEFT JOIN auf multilang, 1x für die gewünschte Sprache und einmal für die "FALLBACK" Sprache sowie mit der COALESCE() Funktion.
Sobald aber eine Sprache hinzukommt, muss ein weiterer LeftJoin verwendet werden!
André Laugks
nö, muss nich, sie will ja immer die nur einmal die gewünschte Sprache und dann als zweites und letztes (=Fallback) die Fallback-Sprache benutzen. Im LEFT JOIN auf multilang gibt sie/es dann immer die zu verwendende "Wunschsprachen"-Id an. Nix mit extra JOIN.
FF
yo,
dann als zweites und letztes (=Fallback) die Fallback-Sprache benutzen.
und warum willst du auf den Fallbacksprache einen zweiten LEFT JOIN machen und nicht einen INNER JOIN ?
Ilja
Weil niemand unfehlbar ist und auch Fallback-Sprachen mal Lücken haben können. In solch einem Fall würde dann gar kein Record zurückgegeben werden. Mit LEFT JOIN gibt es zwar dann wieder einen NULL Wert, aber den können wir ja mit COALESCE abfangen: COALESCE(wunschsprache.Text, fallbacksprache.Text, '[nothing defined]') ... einen Pseudo-Hinweis-Platzhalter halte ich für besser als einen Fehler oder gar keine Anzeige.
Cheers, Frank
Hallo,
vielen Dank für eure Antworten.
Also ich habe jetzt die multilanguage tabelle zweimal leftgejoint gegen die produkttabelle:
SELECT COALESCE(ml.text, mll.text, 'fallback')
FROM produkte AS p
LEFT JOIN multilanguage AS ml
ON p.name = ml.id
AND p.produkt_id = produkt_id
AND ml.language = wunschsprache
LEFT JOIN multilanguage AS mll
ON p.name = ml.id
AND p.produkt_id = produkt_id
AND mll.language = fallbacksprache
Hier erhielt ich jedoch wegen des Left-Joins und bei nicht definierten Spalte im Ergebnis NULL-rows, also habe ich noch GROUP BY p.name hinzugefügt. Kann ich hierbei davon ausgehen, dass die Ergebnisse immer so gruppiert werden, dass ich entweder die wunschsprache oder die fallbacksprache im Ergebnis habe? Hoffe das war verständlich?
Des weitere würde ich gerne bei der Abfrage noch einen weiteren Wert abfragen, der mir praktisch Auskunft gibt, welcher der COALESCE-Werte genommen wurde. Also wenn ml.text genommen wurde, also nicht NULL war, soll dieser Wert 1 sein, wurde mll.text genommen soll 2 etc.
Wie kann ich soetwas realisieren?
Gruß
Hi,
du kannst keine "NULL-rows" erhalten. Entweder du erhältst _keine_ Rows, dann sind die Spalten dieser "_keine_" Rows auch NULL. Und dafür hast du ja COALESCE.
Zowu? Äh, wozu bitte GROUP BY?
Die JOIN Klausel "ON p.name = ml.id" scheint mir auch etwas bisweilen extremst sinnfrei. Du verbindest den Namen (Text?) der Produkts aus der Produkt-Tabelle mit der Id (Zahl??) der MultiLanguage-Tabelle? Kein Wunder, dass du NULL-Rows bekommst.
Und woher kommt "produkt_id"?
Mal künstlich konstruiert, du hast die Tabellen
"Produkt" (Id int, Name varchar(255))
"MultiLanguage" (produkt_id int, language char(2), eigenschaft varchar(255), text varchar(255))
... joinst dann (1) auf MultiLanguage mit den Bedingungen
on multilanguage.produkt_id = produkt.id
and multilanguage.language = 'cn'
and multilanguage.eigenschaft = 'produktname'
und dann (2) noch mal für die Fallback-Sprache
on multilanguage.produkt_id = produkt.id
and multilanguage.language = 'en'
and multilanguage.eigenschaft = 'produktname'
für (1) bekommst du (k)eine Row, keine Row heisst, die Spalt MultiLanguage.Text ist nicht vorhanden und damit ihr Wert NULL. Falls es doch Rows gibt aus diesem LEFT JOIN, dann kann die .Text Spalte immer noch NULL sein, weil ein Depp vergessen hat, da einen Wert einzutragen. Das ist aber völlig belanglos, du benutzt ja COALESCE.
für (2) bekommst du hoffentlich genau 1 Row, oder ...
Wenn du dann noch wissen willst, aus welcher Sprache der finale Wert gekommen ist, dann verwendest du ... na, rate mal, COALESCE() ... nur mit einem Feld, welches bezeichnend für die Sprache ist ... aber auch NULL sein kann, wenn's keinen Wert in der Sprache hat.
Mein Gott, das kann doch nun wirklich nicht so kompliziert sein.
Ciao, Frank
Hallo!
Hole ich id 1 auf English ist dies ja kein Problem. Bei id 2 hingegen schon. Hier soll er mir einfach de ausliefern.
Wie kann ich das bewerkstelligen?
Per SQL sollte das nur mit einer eigenen SQL-Funktion gehen. in der Du das SELECT absetzt und auswertest bzw. Fallback abbildest und einen Datensatz zurück gibst.
Du könntest aber eine Funktion innerhalb Deiner Applikation bauen, der Du alle Sprachvarianten eines Produktest übergibst und dann in der Funktion entscheidest welche Sprache Du zurück gibst.
Viele Grüße
André Laugks