根据结果​​集从 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 的使用显然需要

  1. 从来没有任何语言与所说 M.C。 (ID = 0 或 ID = -100) 被实际添加,永远不会。
  2. 查询构造函数在形成然后在列表中时总是添加 M.C。对它来说,虽然在基于 NULL 的方式中,它只会将实际值放在那里,而 NULL 在查询模板本身中单独计算。