2011-07-28 145 views
0

我想這是或多或少瑣碎的事情,但在這裏不言而喻...的MySQL查詢關係表

我有幾個關係表中,我試圖找回取決於2個值的行。這裏是我的查詢到目前爲止:

SELECT `inventory`.*, `tags`.*, `tags_inv`.*, `categories`.*, `categories_inv`.* 
FROM (`tags`) 
LEFT JOIN `tags_inv` ON `tags_inv`.`tag_id` = `tags`.`tag_id` 
LEFT JOIN `inventory` ON `inventory`.`inventory_id` = `tags_inv`.`inv_id` 
LEFT JOIN `categories_inv` ON `categories_inv`.`inv_id` = `inventory`.`inventory_id` 
LEFT JOIN `categories` ON `categories`.`cat_id` = `categories_inv`.`cat_id` 
WHERE `categories`.`cat_id` = 1 
AND `inventory`.`inv_name` LIKE '%p%' 
OR `inventory`.`inv_dim_w` LIKE '%p%' 
OR `inventory`.`inv_dim_l` LIKE '%p%' 
OR `inventory`.`inv_dim_h` LIKE '%p%' 
OR `tags`.`tag_description` LIKE '%p%' 
ORDER BY `inventory`.`inv_name` 

的問題是,我的查詢從我的數據庫選擇任何項目(像它忽略cat_id),但我想在這種情況下cat_id 1只選擇行...
有沒有一種快速合理的方法來解決這個問題? :)

在此先感謝!

回答

4

在WHERE子句中使用括號將所有OR條件組合在一起。因爲您在WHERE中具有AND和OR,所以忽略所有OR分支的cat_id = 1過濾器。

+0

+1是的,令人驚訝的是許多程序員不理解布爾運算符的優先級,並如何影響邏輯表達式。恕我直言,離散數學是程序員最重要的課程! –

+0

呃......是的,我正在嘗試括號,但由於某種原因,我把他們在錯誤的地方,導致語法錯誤,所以我認爲它太簡單了,是真實的=)大聲笑感謝您的幫助! – errata

4
  • 提醒自己什麼a LEFT JOIN b的含義。這意味着,我們想要所有行的表a的行是否在表b中有匹配的行。您爲所有連接使用了LEFT JOIN,但是您在WHERE子句中的條件意味着您確實需要INNER JOIN。

  • 檢查布爾運算符的優先順序。並結合更緊密比OR(這是所有的編程語言,而不僅僅是SQL真),所以你的WHERE子句不等價的:

    WHERE (`categories`.`cat_id` = 1 AND `inventory`.`inv_name` LIKE '%p%') 
        OR `inventory`.`inv_dim_w` LIKE '%p%' 
        OR `inventory`.`inv_dim_l` LIKE '%p%' 
        OR `inventory`.`inv_dim_h` LIKE '%p%' 
        OR `tags`.`tag_description` LIKE '%p%' 
    

    您需要使用括號來控制自然的運算符優先級。

    WHERE `categories`.`cat_id` = 1 AND 
        (`inventory`.`inv_name` LIKE '%p%' 
        OR `inventory`.`inv_dim_w` LIKE '%p%' 
        OR `inventory`.`inv_dim_l` LIKE '%p%' 
        OR `inventory`.`inv_dim_h` LIKE '%p%' 
        OR `tags`.`tag_description` LIKE '%p%') 
    
  • 利用與領先的通配符LIKE模式匹配謂詞意味着你的查詢無法使用索引來提高效率。所以它必須讀取您的庫存和標籤表的每一行以評估模式匹配。要解決這個問題,您可以使用全文搜索工具,或者向包含您正在搜索的'p'的表添加另一列。

    WHERE `categories`.`cat_id` = 1 
        AND (`inventory`.`has_p` = 1 OR `tags`.`has_p` = 1) 
    
  • 很難優化或表達式使用索引,因爲MySQL在大多數情況下限制,它可以使用每個表僅供參考一個索引。解決方法是運行多個查詢並將它們聯合在一起。這樣,對錶的每個引用都可以使用自己的索引。

    SELECT ... WHERE `categories`.`cat_id` = 1 AND `inventory`.`has_p` = 1 
    UNION ALL 
    SELECT ... WHERE `categories`.`cat_id` = 1 AND `tags`.`has_p` = 1 
    
+0

+1對於很好的解釋!謝謝! – errata