2011-05-21 53 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子句会工作得更快(它不会侵犯你的加入)