2016-10-04 91 views
1

我有一個產品表和一個單獨的表,其中列出了這些產品的各種翻譯。基本設置看起來是這樣的:翻譯的SQL壓扁表

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 one約旋轉和this one其中最好的建議(性能明智)好像是用case語句的例子擺挖,但我努力將它們應用到我的情況。使用第二個鏈接中的case語句可以讓翻譯成線性,但並不會減少項目總數。我正在處理4000萬行(最終有十幾個連接),所以速度非常關鍵,並且使用與所有這些數據截然不同的選擇只會導致性能下降,我需要將數據從select語句中清除出去。

是否有一些技巧我失蹤?

編輯:我應該注意,有時在翻譯的描述中有'EN-US'的真實值(不要問爲什麼,我沒有設計這個),那些需要覆蓋原文說明,所以我不能只是SELECT WHERE Language != 'EN-US'或類似的。還有更多的語言不僅僅是英語和法語,我只是爲了演示而簡化了它。

回答

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的行,但具有不同的語言值。

+0

出於好奇,那裏的GROUP BY語句的目的是什麼?如果我離開它,我得到一個錯誤,但我不知道爲什麼有必要開始。 – thanby

+1

它將爲每個組返回一行(此處爲ProductID)。然後,您只需使用MAX()等集合函數來指定您希望給定組的最大值(每種語言只有一個)。 –

1

最簡單和最快的或者是有條件的聚集或連接:

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 - 這樣更有效。

+0

這兩個答案都很好,我希望我能接受這兩個答案。謝謝你的幫助。 – thanby