2012-12-14 55 views
0

首先讓我描述一些背景。我們有一個包含我們所有產品的表格,以及一個包含「產品標籤」(材料/尺寸/類型)列表的表格和一個包含分配給產品的標籤列表的表格('tag_id'= > 1(材料),「值」 =>「黃金」,「產物」 => 123)如何在MySQL中執行多個LEFT JOIN?

我試圖使用類似於此的查詢來濾除某些產品,但它不似乎不工作。任何人都能向正確的方向提供一些指引嗎?

SELECT DISTINCT `products`.* FROM `products`,`product_assigned_tags` 
LEFT JOIN `product_assigned_tags` AS tags_0 ON tags_0.`tag_id` = 1 
LEFT JOIN `product_assigned_tags` AS tags_1 ON tags_1.`tag_id` = 2 
WHERE (
    ((tags_0.`value` = 'silver') AND (tags_0.`value` != 'gold')) AND 
    ((tags_1.`value` = 'small') AND (tags_1.`value` != 'large')) 
) AND (`products`.`type` = '2' OR `products`.`type` = '1') LIMIT 0, 30 
+2

你的隱無效組合內連接和左連接。請發佈您的表格結構以及您希望查詢的數據樣本,以幫助我們瞭解您所追求的內容。 –

+0

最好顯示您的預期輸出。 +1 @MichaelBerkowski – bonCodigo

+0

@Michael:實際上,OP查詢中沒有任何實際的LEFT連接。 WHERE子句中的謂詞否定了「左連接」的任何「外部」性質,使它們等同於「內連接」。那第一個連接實際上是一個CROSS連接。 – spencer7593

回答

1

有沒有在您的查詢的一些問題。

首先,您有一個CROSS JOIN,它將生成一個笛卡爾積,從products返回的每一行都將與product_assigned_tags中的每一行匹配。

而且,你接下來的兩個連接是不實際的離開了連接(它們不是外部聯接),由於WHERE子句中的謂語。 value = 'foo'的檢查有效地否定了外連接。

此外,您的一些謂詞是多餘的。

如果value = 'silver'的計算結果爲真,則value != 'gold'保證爲真,不需要包含該不等式謂詞。


這真的好像product_assigned_tags表將與商品相關的,具有product_id列的外鍵products.id。 (不具有任何模式定義,我只是在那做一個猜測

SELECT DISTINCT p.* 
    FROM `products` p 
    JOIN `product_assigned_tags` tags_0 
    ON tags_0.product_id = p.id 
    AND tags_0.`tag_id` = 1 
    AND tags_0.`value` = 'silver' 
    JOIN `product_assigned_tags` tags_1 
    ON tags_1.product_id = p.id 
    AND tags_1.`tag_id` = 2 
    AND tags_1.`value` = 'small' 
WHERE p.`type` IN ('1','2') 
ORDER BY 1 
LIMIT 0,30 

問:我將如何去使用連接處理一個「OR」的情況下呢?例如:客戶端選擇查看所有產品與材料「金」或「銀」

?答:表達連接謂詞的OR條件,例如

AND tags_0.`value` IN ('silver','gold') 

到這相當於:

AND (tags_0.`value` = 'silver' OR tags_0.`value` = 'gold') 
+0

這似乎是合乎邏輯的方式。但是,我將如何處理JOIN的'OR'情況? 例如:客戶已選擇查看所有含有「金」或「銀」材質的產品? – R4wizard

+0

@ R4wizard:我會在JOIN謂詞中表達OR條件。 tags_0.value ='gold'或tags_0.value ='silver'。由於AND和OR之間的優先順序,請確保將該OR表達式括在括號內。回答上面更新。 – spencer7593