2017-07-31 57 views
1

我看起來像這樣的兩個表:行作爲列與查找表

汽車

+--------+-----------+-------+---------+ 
| car_id | attribute | value | brand | 
+--------+-----------+-------+---------+ 
|  1 | colore | rosso | Ferrari | 
|  1 | prezzo | 100 | Ferrari | 
|  2 | couleur | bleu | Renault | 
|  2 | prix  | 50 | Renault | 
|  3 | colore | blu | Ferrari | 
|  3 | prezzo | 100 | Ferrari | 
+--------+-----------+-------+---------+ 

翻譯

+--------------------+----------------+---------+----------------------+------------------+ 
| original_attribute | original_value | brand | translated_attribute | translated_value | 
+--------------------+----------------+---------+----------------------+------------------+ 
| colore    | rosso   | Ferrari | color    | red    | 
| prezzo    | 100   | Ferrari | price    | 100    | 
| colore    | blu   | Ferrari | color    | blue    | 
| couleur   | bleu   | Renault | color    | blue    | 
| prix    | 50    | Renault | price    | 50    | 
+--------------------+----------------+---------+----------------------+------------------+ 

我試圖去一個如下所示的表格:

+-------------------+-------+-------------+--------------------+ 
| translated_car_id | color | price  | translated_brand | 
+-------------------+-------+-------------+--------------------+ 
|     1 | red |   100 | Ferrari   | 
|     2 | blue |   50 | Renault   | 
|     3 | blue |   100 | Ferrari   | 
+-------------------+-------+-------------+--------------------+ 

目前,我正在使用下面的代碼。它有效,但速度極慢。

SELECT 
    car_id translated_car_id, 
    MAX(CASE 
     WHEN translations.translated_attribute = 'color' THEN translations.translated_value 
    END) color, 
    MAX(CASE 
     WHEN translations.translated_attribute = 'price' THEN translations.translated_value 
    END) price, 
    brand translated_brand 
FROM 
    cars c 
     INNER JOIN 
    translations ON (c.attribute = translations.original_attribute 
     AND c.brand = translations.brand 
     AND c.value = relations.original_value) 
GROUP BY c.car_id 

有人有關於如何使查詢或結構更有效的想法?會真的很感激它。

在此先感謝

+0

添加language_id列 - 它將幫助您按語言過濾翻譯,而無需執行MAX()和CASE()魔術 – iXCray

+0

使用語言而不是品牌進行翻譯。所以你不需要複製法拉利和菲亞特的翻譯。 –

+0

桌子上有沒有索引?當您運行查詢時,查詢是否受限或者他們是否試圖獲取大量數據(如報告或批處理)?大概多少數據和多慢? – AlwaysLoadingData

回答

0

從我能找到MySQL沒有散的比賽,這將是有益的在這裏。所以我假設一切都是作爲嵌套循環連接完成的。

我擔心的是,由於沒有翻譯索引,因此汽車中的每一行都必須掃描翻譯表以找到匹配的行。

我會在翻譯(original_value,brand,original_attribute)上推薦一個聚集索引。 (ms-sql最適合於大多數具體的第一件事情是平等的,不知道MySql)這樣它就可以直接到它需要匹配的行。這應該允許快速完成一輛車的查詢。

如果您可以減少從製造商到語言的翻譯,這對於翻譯表的大小肯定會有所幫助,但是您必須確保它能夠與您的數據集一起工作,因爲它確實帶走了一定程度的靈活性。

我認爲MySql能夠使用cars上的索引來有效地處理GROUP BY,但是我會提出一個更加規範化的模式,你不需要group by。

car 
------------- 
car_id 
brand 

car_attribute 
------------ 
car_id 
attribute 
value 
clustered_index(car_id, attribute) 

brand_attribute 
------------ 
brand_attribute_id 
brand 
attribute 
translated_attribute 
clustered_index(brand, translated_attribute) 

brand_attribute_value 
------------ 
brand_attribute_id 
value 
translated_value 
clustered_index(brand_attribute_id, value) 

而這是查詢做到這一點。

SELECT 
    car.car_id, 
    color_brand_value.translated_value AS color, 
    price_brand_value.translated_value AS price, 
    car.brand 
FROM 
    car 

    INNER JOIN brand_attribute AS color_brand 
     ON color_brand.brand = car.brand 
      AND color_brand.translated_attribute = 'color' 
    INNER JOIN car_attribute AS color_attribute 
     ON color_attribute.car_id = car.car_id 
      AND color_attribute.attribute = brand.attribute 
    INNER JOIN brand_attribute_value AS color_brand_value 
     ON color_brand_value.brand_attribute_id = color_brand.brand_attribute_id 
      AND color_brand_value.value = color_attribute.value 

    INNER JOIN brand_attribute AS price_brand 
     ON price_brand.brand = car.brand 
      AND price_brand.translated_attribute = 'price' 
    INNER JOIN car_attribute AS price_attribute 
     ON price_attribute.car_id = car.car_id 
      AND price_attribute.attribute = brand.attribute 
    INNER JOIN brand_attribute_value AS price_brand_value 
     ON price_brand_value.brand_attribute_id = price_brand.brand_attribute_id 
      AND price_brand_value.value = price_attribute.value 

這樣做肯定比較複雜。在你的情況下,我不確定它是否更好,但是如果第一個選項不夠好,可以考慮一些事情。

我的背景是在mssql中,所以可能會有差異,我不知道。如果我錯過了或發生了錯誤,請留下評論。

+0

添加聚集索引幫助了幾個數量級 - 非常感謝你! – Peter

+0

我很高興能夠提供幫助 – AlwaysLoadingData