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
-- 它更有效。
我有一个 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
-- 它更有效。