【问题标题】:SQL flattening tables of translationsSQL 扁平化翻译表
【发布时间】:2017-02-13 04:50:24
【问题描述】:

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

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

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

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 onethis one 这样的示例,其中最好的建议(性能方面)似乎是使用大量案例陈述,但我正在努力将它们应用于我的情况。使用第二个链接中的 case 语句可以使翻译成为线性的,但它不会减少项目的总数。我正在处理 4000 万行(最终有十几个连接),因此速度至关重要,使用与所有这些数据不同的选择只会降低性能,我需要从选择语句中对数据进行清理。

我错过了什么技巧吗?

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

【问题讨论】:

    标签: sql-server join pivot


    【解决方案1】:

    您似乎需要从您的产品表中返回英文描述。使用条件求和聚合:

    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(),以便从翻译表中优先考虑英文翻译 - 如果它为空,则从产品表中获取原始描述。

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

    【讨论】:

    • 出于好奇,GROUP BY 语句的目的是什么?如果我忽略它,我会收到一个错误,但我不确定为什么需要开始。
    • 它将为每个组返回一行(此处为:ProductID)。然后,您只需使用 MAX() 之类的聚合函数来指定您想要给定组的最大值(每种语言只有一个)。
    【解决方案2】:

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

    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;
    

    如果要建表,可以加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';
    

    这将返回所有产品。如果你知道每个产品至少有一个翻译,那么使用inner join而不是full join——这样效率更高。

    【讨论】:

    • 这两个答案都很棒,我希望我能同时接受。感谢您的帮助。
    猜你喜欢
    • 2019-04-23
    • 2016-01-14
    • 2012-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-08
    相关资源
    最近更新 更多