I've been trying to work with languages in databases for a little while, but this one has me stumped.
So here's the simplified structure of two tables
DATA
descID | descOriginal | deptID | Other Data
-----------|--------------|------- |-----------
10 | TshirtsNL | 1 | ...
20 | TrousersNL | 1 | ...
30 | ShoesNL | 1 | ...
and
LANG
descID |descTranslated| langID
-----------|--------------|-------
10 | TshirtsDE | 1
10 | TshirtsFR | 2
10 | TshirtsEN | 3
So basically, the original description sits in the first table, along with other needed data. However, the translated description sits in another table for when the original description needs to be translated.
To complicate things further: Not all rows in the LANG table have been filled to correspond with the data in the DATA table (this only happens when the customer fills in their translation). This means I can't rely on a simple JOIN WHERE l.descID = d.descID
.
I've been trying different kinds of joins and coalesce, but I can't seem to make it work.
Below is not supported in my Firebird version (1.5), but might work if your Database supports derived tables.
I thought something like this could work:
SELECT COALESCE(lang.descTranslated, data.descOriginal) AS desc
FROM
(SELECT descID, descOriginal FROM data WHERE deptID =
:deptID) data
LEFT JOIN
(SELECT descID, descTranslated FROM lang) lang
ON
data.descID = lang.descID
But Firebird doesn't seem to like these kind of statements (or I'm missing something), because the following test SQL throws an error "unknown token SELECT"
SELECT * FROM (SELECT descID FROM data)
As already commented by Val Marinov, derived tables were introduced in Firebird 2.0 (in 2006). However for your problem, you don't need to use derived tables:
To get the result you want:
select coalesce(lang.desctranslated, data.descoriginal)
from data
left join lang
on data.descid = lang.descid
is sufficient. If you want to specify a specific language, then using the following would suffice:
select coalesce(lang.desctranslated, data.descoriginal)
from data
left join lang
on data.descid = lang.descid
where lang.langid = 2 or lang.langid is null
or pushing the condition down to the join:
select coalesce(lang.desctranslated, data.descoriginal)
from data
left join lang
on data.descid = lang.descid and lang.langid = 2
I have tested this with Firebird 1.5.6 and the sample data from your question.
While Firebird 1.x did not support anonymous derived tables it did support views.
CREATE VIEW DEPT_DESCS AS
SELECT lang.descID, lang.descTranslated as Dept_Description, lang.langID, languages.lang_name
FROM lang
LEFT JOIN DATA ON DATA.descID = lang.descID
JOIN languages ON languages.lang_id = lang.langID
WHERE DATA.descID is not null -- would not need translations for non-existing lines
ORDER BY lang.descID, lang.langID DESC
UNION ALL
SELECT data.descID, data.descOriginal, NULL, NULL FROM data
And now you can select from that view
SELECT first(1) * FROM DEPT_DESCS
WHERE ( langID in (5,8,10) or langID is NULL )
AND descID=10
ORDER by langID /* DESC */ NULLS LAST
See https://www.firebirdsql.org/manual/nullguide-sorts.html
One may also use zero or negative number instead of null for non-translated descriptions.
CREATE VIEW DEPT_DESCS AS
SELECT lang.descID, lang.descTranslated as Dept_Description, lang.langID, languages.lang_name
.....
ORDER BY lang.descID, lang.langID DESC
UNION ALL
SELECT data.descID, data.descOriginal, -100 /* or 0 */, NULL FROM data
That way the second query gets a bit more simple.
SELECT first(1) * FROM DEPT_DESCS
WHERE langID in (5,8,10, -100 /* or 0 */ )
AND descID=10
ORDER by langID DESC
However this use of magic constants
would obviously demand that
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.