2011-05-21 49 views
3

我有這個疑問,其運行良好:MySQL查詢問題 - 嵌套和/或聲明

SELECT count(distinct p.products_id) as total 
FROM (products p 
     LEFT JOIN manufacturers m 
     USING(manufacturers_id), products_description pd, 
       categories c, products_to_categories p2c) 
LEFT JOIN meta_tags_products_description mtpd 
      ON mtpd.products_id= p2c.products_id 
      AND mtpd.language_id = 1 
WHERE (p.products_status = 1 AND p.products_id = pd.products_id 
     AND pd.language_id = 1 AND p.products_id = p2c.products_id 
     AND p2c.categories_id = c.categories_id 
     AND (
      (pd.products_name LIKE '%3220%' 
      OR p.products_model LIKE '%3220%' 
      OR m.manufacturers_name LIKE '%3220%' 
      OR (mtpd.metatags_keywords LIKE '%3220%' 
       AND mtpd.metatags_keywords !='') 
      OR 
      (mtpd.metatags_description LIKE '%3220%' 
       AND mtpd.metatags_description !='') 
      OR 
       pd.products_description LIKE '%3220%' 
      ) 
      ) 
    ) 

但我想無論是尋找那些WHERE子句,或給出一個數字關鍵字值作爲例子,搜索對於產品ID,只需將此添加到上一個查詢中即可:

OR (p.products_id=3220) 

但由於某種原因,加法凍結了mysql服務器。它只是繼續執行查詢,它永遠不會結束。我必須手動重新啓動服務器。我做錯了什麼?

+1

哇。你知道你可以對齊和縮進SQL,對吧? – GolezTrol 2011-05-21 16:39:00

+0

該查詢看起來很醜! – Lobo 2011-05-21 16:46:03

+0

你究竟在哪裏添加OR?最後一個括號之後? – squawknull 2011-05-21 16:46:31

回答

4

當您添加或結束(假設你的最後一個括號之後加入的話),你正在創建一個笛卡兒連接爲你無效,你放置你的WHERE子句(p.products_id = pd.products_id在JOIN條件,p.products_id = p2c.products_idp2c.categories_id = c.categories_id)。另外,爲什麼要在圓括號內放置初始表格(產品,製造商,產品描述,類別,產品類別)?相反,嘗試更多的東西是這樣的:

SELECT count(distinct p.products_id) as total 
FROM products p 
LEFT JOIN manufacturers m USING(manufacturers_id) 
LEFT JOIN products_description pd using products_id 
LEFT JOIN categories c USING (categories_id) 
LEFT JOIN products_to_categories p2c USING (products_id) 
LEFT JOIN meta_tags_products_description mtpd 
      ON mtpd.products_id= p2c.products_id 
      AND mtpd.language_id = 1 
WHERE (p.products_status = 1 
     AND pd.language_id = 1 
     AND (
      (pd.products_name LIKE '%3220%' 
      OR p.products_model LIKE '%3220%' 
      OR m.manufacturers_name LIKE '%3220%' 
      OR (mtpd.metatags_keywords LIKE '%3220%' 
       AND mtpd.metatags_keywords !='') 
      OR 
      (mtpd.metatags_description LIKE '%3220%' 
       AND mtpd.metatags_description !='') 
      OR 
       pd.products_description LIKE '%3220%' 
      ) 
      ) 
    ) 
     OR (p.products_id=3220) 

我不明白p.products_status = 1 AND pd.language_id = 1你的情況的意思,所以你可能需要調整如何將這些都包含在JOIN。

+0

我無法真正修改這個查詢。那麼,我想我可以,但它迫使我修改更多的PHP代碼。你能否建議一種方法來添加該OR語句而不修改查詢的其餘部分(或儘可能少)?無論如何,我試過你的解決方案,似乎工作得很好。我無法使用'LEFT JOIN類別c USING categories_id',因爲該字段只存在於類別中,而不存在於其他表格中。 – AJJ 2011-05-21 18:46:14

+0

根據您的原始查詢,categories_id字段存在於類別表和products_to_categories表中。我強烈建議修改代碼來清理查詢,但如果你真的無法做到這一點,只需將連接條件添加到OR子句中,例如'OR(p.products_id = pd.products_id AND p.products_id = p2c.products_id AND p2c.categories_id = c.categories_id AND p.products_id = 3220)'。這應該至少解決你的笛卡兒連接問題,但這會造成一個可悲的難看的查詢。 – squawknull 2011-05-21 21:45:02

1

使用OR比使用AND慢。您可以嘗試在這種情況下,將新條件放在WHERE的開頭,而不是末尾。

另一種解決方案是編寫兩個單獨的查詢,一個包含所有的LIKE,另一個包含使用products_id的查詢。然後,使用UNION來組合這些查詢的結果。此解決方案通常比使用帶有OR的複雜表達式更快。理論上UNION ALL甚至更快,但如果它們與兩個查詢中的條件相匹配,則可能會導致雙記錄。

+0

我不能真的以這種方式修改查詢。我應該可能已經解釋了這個查詢(大部分是)由ZenCart通過PHP組成的。我可以修改它的一些位,但不能運行兩個單獨的查詢,據我所知。 – AJJ 2011-05-21 18:29:49

+0

OR開頭的好處究竟是什麼?只有速度? – AJJ 2011-05-21 18:34:00

+0

我給了這個嘗試,但我得到了同樣的結果:mysqld停止響應,我必須手動重新啓動它。任何想法爲什麼發生這種情況如果查詢沒有返回行或錯誤,我可以做一些事情,這樣我不能做太多事情。有沒有一種方法來調試呢?有沒有辦法知道服務器上次運行的查詢是做什麼的? – AJJ 2011-05-21 18:50:21

0

我知道這並不總是可能的,但如果你可以改變你的LEFT JOIN到INNER JOIN嵌套AND/OR子句會工作得更快(它不會侵犯你的加入)