开发者

mysql query problem - nested and/or statements

I have this query which runs fine:

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.pro开发者_如何学Pythonducts_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%'
            ) 
           ) 
      )

But I want to either search for those WHERE clauses or, given a numeric keyword value as in the example, search for the products id by just adding this to the previous query:

 OR (p.products_id=3220)

But for some reason that addition freezes the mysql server. It just keeps executing the query and it never ends. I have to manually restart the server. What is it that I am doing wrong?


When you add the OR to the end (assuming you're adding it after the last paren), you are creating a cartesian join as you're invalidating your JOIN conditions that you placed in your WHERE clause (p.products_id = pd.products_id, p.products_id = p2c.products_id and p2c.categories_id = c.categories_id). Also, why are you putting the initial tables (products, manufacturers, products_description, categories, products_to_categories) inside of parenthesis? Instead, try something more like this:

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)

I do not understand what p.products_status = 1 AND pd.language_id = 1 mean in your case, so you may need to adjust how those are included in the JOIN.


Using OR is slower than using AND. You could try in this case, to put the new condition at the beginning of the WHERE instead of at the end.

Another solution would bu two write two separate queries, one with all the LIKEs and another using the products_id. Then, use UNION to combine the result of those queries. This solution is often faster than using complex expressions with OR. UNION ALL is even faster theoretically, but it may result in double records if they match the conditions in both queries.


I know it is not always possible, but if you can change your LEFT JOIN to INNER JOIN the nested AND / OR clauses will work much quicker (it will not invade your join)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜