根据结果集从 table 中选择行
Selecting rows from table based on resultset
一段时间以来,我一直在尝试使用数据库中的语言,但这个让我很困惑。
所以这是两个tables
的简化结构
DATA
descID | descOriginal | deptID | Other Data
-----------|--------------|------- |-----------
10 | TshirtsNL | 1 | ...
20 | TrousersNL | 1 | ...
30 | ShoesNL | 1 | ...
和
LANG
descID |descTranslated| langID
-----------|--------------|-------
10 | TshirtsDE | 1
10 | TshirtsFR | 2
10 | TshirtsEN | 3
所以基本上,原始描述位于第一个 table,连同其他需要的数据。但是,当原始描述需要翻译时,翻译后的描述位于另一个 table 中。
更复杂的是:并非 LANG table 中的所有行都已填充以与 DATA table 中的数据相对应(这仅在客户填写他们的翻译时发生)。这意味着我不能依赖简单的 JOIN WHERE l.descID = d.descID
.
我一直在尝试不同类型的联接和合并,但我似乎无法让它发挥作用。
我的 Firebird 版本 (1.5) 不支持以下内容,但如果您的数据库支持派生的 tables 可能会起作用。
我认为这样的方法可行:
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
但是 Firebird 似乎不喜欢这些语句(或者我遗漏了什么),因为下面的测试 SQL 会抛出错误 "unknown token SELECT"
SELECT * FROM (SELECT descID FROM data)
正如 Val Marinov 所评论的那样,派生表是在 Firebird 2.0(2006 年)中引入的。但是对于您的问题,您不需要使用派生表:
得到你想要的结果:
select coalesce(lang.desctranslated, data.descoriginal)
from data
left join lang
on data.descid = lang.descid
足够了。如果要指定特定语言,则使用以下内容就足够了:
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
或将条件下推到连接:
select coalesce(lang.desctranslated, data.descoriginal)
from data
left join lang
on data.descid = lang.descid and lang.langid = 2
我已经用 Firebird 1.5.6 和您问题中的示例数据对此进行了测试。
虽然 Firebird 1.x 不支持匿名派生表,但它支持视图。
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
现在您可以select从那个视图
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
见https://www.firebirdsql.org/manual/nullguide-sorts.html
对于未翻译的描述,也可以使用零或负数而不是 null。
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
这样第二个查询就变得更简单了。
SELECT first(1) * FROM DEPT_DESCS
WHERE langID in (5,8,10, -100 /* or 0 */ )
AND descID=10
ORDER by langID DESC
但是 magic constants
的使用显然需要
- 从来没有任何语言与所说 M.C。 (ID = 0 或 ID = -100) 被实际添加,永远不会。
- 查询构造函数在形成然后在列表中时总是添加 M.C。对它来说,虽然在基于 NULL 的方式中,它只会将实际值放在那里,而 NULL 在查询模板本身中单独计算。
一段时间以来,我一直在尝试使用数据库中的语言,但这个让我很困惑。
所以这是两个tables
的简化结构DATA
descID | descOriginal | deptID | Other Data
-----------|--------------|------- |-----------
10 | TshirtsNL | 1 | ...
20 | TrousersNL | 1 | ...
30 | ShoesNL | 1 | ...
和
LANG
descID |descTranslated| langID
-----------|--------------|-------
10 | TshirtsDE | 1
10 | TshirtsFR | 2
10 | TshirtsEN | 3
所以基本上,原始描述位于第一个 table,连同其他需要的数据。但是,当原始描述需要翻译时,翻译后的描述位于另一个 table 中。
更复杂的是:并非 LANG table 中的所有行都已填充以与 DATA table 中的数据相对应(这仅在客户填写他们的翻译时发生)。这意味着我不能依赖简单的 JOIN WHERE l.descID = d.descID
.
我一直在尝试不同类型的联接和合并,但我似乎无法让它发挥作用。
我的 Firebird 版本 (1.5) 不支持以下内容,但如果您的数据库支持派生的 tables 可能会起作用。
我认为这样的方法可行:
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
但是 Firebird 似乎不喜欢这些语句(或者我遗漏了什么),因为下面的测试 SQL 会抛出错误 "unknown token SELECT"
SELECT * FROM (SELECT descID FROM data)
正如 Val Marinov 所评论的那样,派生表是在 Firebird 2.0(2006 年)中引入的。但是对于您的问题,您不需要使用派生表:
得到你想要的结果:
select coalesce(lang.desctranslated, data.descoriginal)
from data
left join lang
on data.descid = lang.descid
足够了。如果要指定特定语言,则使用以下内容就足够了:
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
或将条件下推到连接:
select coalesce(lang.desctranslated, data.descoriginal)
from data
left join lang
on data.descid = lang.descid and lang.langid = 2
我已经用 Firebird 1.5.6 和您问题中的示例数据对此进行了测试。
虽然 Firebird 1.x 不支持匿名派生表,但它支持视图。
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
现在您可以select从那个视图
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
见https://www.firebirdsql.org/manual/nullguide-sorts.html
对于未翻译的描述,也可以使用零或负数而不是 null。
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
这样第二个查询就变得更简单了。
SELECT first(1) * FROM DEPT_DESCS
WHERE langID in (5,8,10, -100 /* or 0 */ )
AND descID=10
ORDER by langID DESC
但是 magic constants
的使用显然需要
- 从来没有任何语言与所说 M.C。 (ID = 0 或 ID = -100) 被实际添加,永远不会。
- 查询构造函数在形成然后在列表中时总是添加 M.C。对它来说,虽然在基于 NULL 的方式中,它只会将实际值放在那里,而 NULL 在查询模板本身中单独计算。