2013-11-22 95 views
3

我發現你可以通過使用子查詢來解決61表連接限制問題。 https://stackoverflow.com/a/20134402/2843690解決了61個表的JOIN限制在子查詢中嵌套子查詢

我試圖找出如何在程序中我工作的擺脫Magento的詳細的產品清單(但我認爲這個問題的答案可以適用於很多容易使用本涉及eav的情況)。需要被連接的表是這個樣子:

catalog_product_entity 
+-----------+----------------+ 
| entity_id | entity_type_id | 
+-----------+----------------+ 
|   1 |    4 | 
|   2 |    4 | 
|   3 |    4 | 
|   4 |    4 | 
|   5 |    4 | 
|   6 |    4 | 
|   7 |    4 | 
|   8 |    4 | 
|   9 |    4 | 
+-----------+----------------+ 

catalog_product_entity_int 
+----------+----------------+--------------+-----------+-------+ 
| value_id | entity_type_id | attribute_id | entity_id | value | 
+----------+----------------+--------------+-----------+-------+ 
|  1 |    4 |   2 |   1 | 245 | 
|  2 |    4 |   3 |   1 | 250 | 
|  3 |    4 |   4 |   1 | 254 | 
|  4 |    4 |   2 |   2 | 245 | 
|  5 |    4 |   3 |   2 | 249 | 
|  6 |    4 |   4 |   2 | 253 | 
|  7 |    4 |   2 |   3 | 247 | 
|  8 |    4 |   3 |   3 | 250 | 
|  9 |    4 |   4 |   3 | 254 | 
+----------+----------------+--------------+-----------+-------+ 

eav_attribute 
+--------------+----------------+----------------+--------------+ 
| attribute_id | entity_type_id | attribute_code | backend_type | 
+--------------+----------------+----------------+--------------+ 
|   1 |    4 | name   | varchar  | 
|   2 |    4 | brand   | int   | 
|   3 |    4 | color   | int   | 
|   4 |    4 | size   | int   | 
|   5 |    4 | price   | decimal  | 
|   6 |    4 | cost   | decimal  | 
|   7 |    4 | created_at  | datetime  | 
|   8 |    3 | name   | varchar  | 
|   9 |    3 | description | text   | 
+--------------+----------------+----------------+--------------+ 

eav_attribute_option 
+-----------+--------------+ 
| option_id | attribute_id | 
+-----------+--------------+ 
|  245 |   2 | 
|  246 |   2 | 
|  247 |   2 | 
|  248 |   3 | 
|  249 |   3 | 
|  250 |   3 | 
|  251 |   4 | 
|  252 |   4 | 
|  253 |   4 | 
|  254 |   4 | 
+-----------+--------------+ 

eav_attribute_option_value 
+----------+-----------+-------------------+ 
| value_id | option_id |  value  | 
+----------+-----------+-------------------+ 
|  15 |  245 | Fruit of the Loom | 
|  16 |  246 | Hanes    | 
|  17 |  247 | Jockey   | 
|  18 |  248 | White    | 
|  19 |  249 | Black    | 
|  20 |  250 | Gray    | 
|  21 |  251 | Small    | 
|  22 |  252 | Medium   | 
|  23 |  253 | Large    | 
|  24 |  254 | Extra Large  | 
+----------+-----------+-------------------+ 

,我正在寫產生的看起來是這樣的SQL查詢程序:

SELECT cpe.entity_id 
, brand_int.value as brand_int, brand.value as brand 
, color_int.value as color_int, color.value as color 
, size_int.value as size_int, size.value as size 

FROM catalog_product_entity as cpe 

LEFT JOIN catalog_product_entity_int as brand_int 
ON (cpe.entity_id = brand_int.entity_id 
AND brand_int.attribute_id = 2) 
LEFT JOIN eav_attribute_option as brand_option 
ON (brand_option.attribute_id = 2 
AND brand_int.value = brand_option.option_id) 
LEFT JOIN eav_attribute_option_value as brand 
ON (brand_option.option_id = brand.option_id) 

LEFT JOIN catalog_product_entity_int as color_int 
ON (cpe.entity_id = color_int.entity_id 
AND color_int.attribute_id = 3) 
LEFT JOIN eav_attribute_option as color_option 
ON (color_option.attribute_id = 3 
AND color_int.value = color_option.option_id) 
LEFT JOIN eav_attribute_option_value as color 
ON (color_option.option_id = color.option_id) 

LEFT JOIN catalog_product_entity_int as size_int 
ON (cpe.entity_id = size_int.entity_id 
AND size_int.attribute_id = 4) 
LEFT JOIN eav_attribute_option as size_option 
ON (size_option.attribute_id = 4 
AND size_int.value = size_option.option_id) 
LEFT JOIN eav_attribute_option_value as size 
ON (size_option.option_id = size.option_id) 
; 

這是比較容易編寫的代碼生成查詢,查詢相當容易理解;然而,要實現61個表連接限制是非常容易的,我使用我的現實生活中的數據。我相信數學說21個整數類型屬性會超過限制,那就是在我開始添加varchar,text和decimal屬性之前。

所以我想出的解決方案是使用子查詢來克服61表限制。

這樣做的一種方法是將連接分組到61個連接的子查詢中。然後所有的團體都會加入。我想我可以弄清楚sql查詢應該是什麼樣子,但編寫代碼來生成查詢似乎很困難。還有一個(儘管是理論上的)問題,如果有足夠的屬性,人們可能再次違反61表格限制。換句話說,如果我有62組61個表,將會出現MySQL錯誤。顯然,人們可以通過將羣組分組到61來解決這個問題。但是這隻會讓代碼更難以編寫和理解。

我認爲我想要的解決方案是在子查詢中嵌套子查詢,以便每個子查詢使用2個表(或一個表和一個子查詢)的單個連接。直觀地看,這種查詢似乎更容易編寫代碼。不幸的是,考慮這些查詢應該是什麼樣子會讓我的大腦受到傷害。這就是爲什麼我需要幫助。

這樣的MySQL查詢會是什麼樣子?

+0

如果您的主要目標是「從Magento獲取詳細的產品列表」,爲什麼您不包含要在平板表索引中查詢的屬性,然後只需從catalog_product_flat_1中執行select *操作?要麼,要麼利用現有的Magento模型創建一個集合,並選擇要顯示的屬性。在我看來,你的SQL解決方案是一個效率低下的方法。 – Axel

+0

@Axel catalog_product_flat要求reindex是最新的,我相信。 catalog_product_flat也沒有我想要的所有信息。至於magento系列,我對magento的內部工作不是很熟悉。到目前爲止,我發現直接的mysql查詢要比使用magento或api快得多。 –

+0

另外,我只是好奇。即使在這種情況下它不實用,它可能對以後的某些事情有用。至少,我認爲這可能很有趣。 –

回答

2

你說得對,通過EAV設計加入太多屬性可能會超出聯接限制。甚至在此之前,可能會有一個實際的連接限制,因爲如此多的連接的成本在幾何上變得越來越高。這有多糟糕取決於服務器的容量,但它可能會低於61.

因此,查詢EAV數據模型以產生結果,就好像它存儲在傳統關係模型中一樣(每列一列屬性)是有問題的。

解決方案:不要用每個屬性的連接來實現,這意味着您不能期望以純粹使用SQL的傳統每行實體格式生成結果。

我不十分熟悉Magento的模式,但我可以從查詢推斷,這樣的事情可能工作:

SELECT cpe.entity_id 
, o.value AS option 
, v.value AS option_value 
FROM catalog_product_entity AS cpe 
INNER JOIN catalog_product_entity_int AS i 
    ON cpe.entity_id = i.entity_id AND i.attribute_id IN (2,3,4) 
INNER JOIN eav_attribute_option AS o 
    ON i.value = o.option_id AND i.attribute_id = o.attribute_id 
INNER JOIN eav_attribute_option_value AS v 
    ON v.option_id = o.option_id; 

IN(2,3,4,...)謂詞中可指定多個屬性。無需添加更多連接即可獲得更多屬性。它們只是以行而不是列的形式返回。

這意味着您必須編寫應用程序代碼來獲取此結果集的所有行並將它們映射到單個對象的字段中。

來自@Axel的評論,聽起來像Magento提供的輔助函數來完成這個功能,消耗一個結果集並將其映射到一個對象中。

+0

不是我正在尋找的東西,但實際上這會更容易實現。謝謝。據我所知,我正在使用Amazon RDS,甚至一個微型實例在61個表連接(甚至是61個表與61個子表的子查詢連接的子查詢)上也沒什麼問題。我想這是相對的,因爲通過Magento或其api進行類似的查詢是非常緩慢的。此外,從我通過查看MySQL日誌所看到的情況來看,Magento並沒有採取更明智的做法,而是實際使用了大量複雜的JOIN(以及使用其平坦索引表)。 –

+0

這個問題的根本問題是它只返回ID而不是來自需要連接的表的值。 – gshauger