根据结果​​集

时间:2017-07-17 09:20:34

标签: php sql firebird

我一直试图在数据库中使用语言一段时间,但这个让我感到难过。

所以这是两个表的简化结构

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

基本上,原始描述位于第一个表中,以及其他所需数据。但是,翻译的描述位于另一个表格中,用于何时需要翻译原始描述。

使事情进一步复杂化:并非所有LANG表中的行都已填充以与DATA表中的数据相对应(这仅在客户填写其翻译时发生)。这意味着我不能依赖简单的JOIN WHERE l.descID = d.descID

我一直在尝试不同类型的连接和合并,但我似乎无法使它工作。

我的Firebird版本(1.5)不支持以下版本,但如果您的数据库支持派生表,则可能会有效。

我认为这样的事情可行:

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)

2 个答案:

答案 0 :(得分:1)

正如Val Marinov已经评论过的,派生表是在Firebird 2.0中引入的(2006年)。但是,对于您的问题,您不需要使用派生表:

获得您想要的结果:

char

就足够了。如果要指定特定语言,则使用以下内容就足够了:

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

我已经使用Firebird 1.5.6和您问题的样本数据进行了测试。

答案 1 :(得分:1)

虽然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 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

对于非翻译的描述,也可以使用零或负数而不是空。

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。