SQL 扁平化翻译表

SQL flattening tables of translations

我有一个 table 产品,还有一个单独的 table 列出了这些产品的各种翻译。基本设置如下所示:

dbo.Products
ProductID | Description
1         | An amazing product
2         | An even more amazing product
3         | Don't buy this one

dbo.ProductTranslations
ProductID | Language | Description
1         | EN-US    | null
1         | FR-CA    | Un produit étonnant
2         | EN-US    | null
2         | FR-CA    | Un produit encore plus étonnant
3         | EN-US    | null
3         | FR-CA    | Ne pas acheter celui-ci

我想做的基本上是将其展平,以便所有产品和翻译都在一个 table 中,并像这样为每个产品压缩成一行:

dbo.FlattenedProducts
ProductID | EN-US_Description            | FR-CA_Description
1         | An amazing product           | Un produit étonnant
2         | An even more amazing product | Un produit encore plus étonnant
3         | Don't buy this one           | Ne pas acheter celui-ci

我研究过像 this one about pivoting and this one 这样的例子,其中最好的建议(性能方面)似乎是使用大量的 case 语句,但我正在努力将它们应用到我的情况中。使用像第二个 link 那样的 case 语句让我使翻译成为线性的,但它不会减少项目的总数。我正在处理 4000 万行(最终有十几行连接),所以速度很关键,使用与所有这些数据不同的 select 只会降低性能,我需要已经清理过的数据select 声明。

我是否缺少一些技巧?

编辑: 我应该注意,有时翻译的描述中有真实值 'EN-US'(不要问为什么,我没有设计这个),并且那些需要覆盖原始描述,所以我不能只是 SELECT WHERE Language != 'EN-US' 或类似的。此外,除了英语和法语外,还有更多语言,我只是为了演示目的对其进行了简化。

您的产品似乎需要 return 英文说明 table。使用条件求和聚合:

SELECT
  p.ProductID,
  MAX(CASE WHEN pt.Language = 'EN-US' THEN COALESCE(pt.Description, p.Description) END) AS ENUS_Description,
  MAX(CASE WHEN pt.Language = 'FR-CA' THEN pt.Description END) AS FRCA_Description
FROM dbo.Products p
LEFT JOIN dbo.ProductTranslations pt ON p.ProoductID = pt.ProductID 
GROUP BY p.ProductID

编辑: 根据您的编辑添加 COALESCE() 以从翻译 table 中优先考虑英语翻译 - 如果为空,则采用原文来自产品的描述 table.

对于更多语言,只需添加看起来像 FR-CA 但具有不同语言值的相应行。

最简单和最快的是条件聚合或连接:

select pt.productid,
       max(case when language = 'EN-US' then description end) as en_us,
       max(case when language = 'CA-FR' then description end) as ca_fr
from ProductTranslations pt
group by productid;

如果要创建 table,可以添加 into FlattenedProducts

join方法是:

select coalesce(pte.productid, ptf.productid) as productid,
       pte.description as us_en,
       ptf.description as ca_fr
from ProductTranslations pte full join
     ProductTranslations ptf
     on pte.productid = ptf.productid and
        pte.language = 'EN-US' and ptf.language = 'CA-FR';

此returns所有产品。如果您知道每个产品至少有一个翻译,那么使用 inner join 而不是 full join -- 它更有效。