MySQL запрос - вложенные и / или операторы - PullRequest
5 голосов
/ 21 мая 2011

У меня есть этот запрос, который работает нормально:

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, либо, учитывая числовое значение ключевого слова, как в примере, выполнить поиск идентификатора продукта, просто добавив его в предыдущий запрос:

 OR (p.products_id=3220)

Но по какой-то причине это дополнение зависает на сервере MySQL. Он просто продолжает выполнять запрос и никогда не заканчивается. Я должен вручную перезапустить сервер. Что я делаю не так?

Ответы [ 3 ]

5 голосов
/ 21 мая 2011

Когда вы добавляете ИЛИ в конец (при условии, что вы добавляете его после последнего парена), вы создаете декартово объединение, так как вы аннулируете условия JOIN, которые вы поместили в предложение WHERE (p.products_id = pd.products_id,p.products_id = p2c.products_id и p2c.categories_id = c.categories_id).Кроме того, почему вы помещаете начальные таблицы (продукты, производители, products_description, Categories, products_to_categories) в круглые скобки?Вместо этого попробуйте что-то более похожее на это:

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.

1 голос
/ 21 мая 2011

Использование OR медленнее, чем использование AND. В этом случае вы можете попытаться поместить новое условие в начало ГДЕ, а не в конец.

Другое решение состоит в том, что два пишут два отдельных запроса, один со всеми LIKE, а другой с использованием products_id. Затем используйте UNION для объединения результатов этих запросов. Это решение часто быстрее, чем использование сложных выражений с OR. UNION ALL даже быстрее теоретически, но может привести к двойным записям, если они соответствуют условиям в обоих запросах.

0 голосов
/ 08 марта 2017

Я знаю, что это не всегда возможно, но если вы можете изменить ЛЕВОЕ СОЕДИНЕНИЕ на ВНУТРЕННЕЕ СОЕДИНЕНИЕ, вложенные предложения И / ИЛИ будут работать намного быстрее (это не повлияет на ваше объединение)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...