使用" AND"和"或"在SQL查询中

时间:2015-06-20 04:37:18

标签: mysql sql performance

我正在尝试优化查询。表中有三种不同的查找,我认为这些查找不是必需的。

这是原始查询,我想优化。

SELECT DISTINCT(productid) FROM q_products
      WHERE visibility=1 and status=0 AND productid IN (productidList)
        UNION ALL 
      SELECT DISTINCT(q_products.productid) FROM q_products,q_product_apply_access 
        WHERE q_products.productid=q_product_apply_access.productid 
        AND q_product_apply_access.partnerid='partnerid'
        AND q_product_apply_access.apply_status=0 
        AND q_products.visibility=3 AND q_products.status=0 
        AND q_products.productid IN (productidList)
        UNION ALL
      SELECT DISTINCT(q_products.productid) FROM q_products,q_product_aff_access 
        WHERE q_products.productid=q_product_aff_access.productid 
        AND q_product_aff_access.accid='accountid' 
        AND q_products.visibility=2 AND q_products.status=0 
        AND q_products.productid IN (productidList)

让我带你完成这个问题,

1)我从productid选择了q_productsvisibility=1并且同样位于status=0

productidList

2)我现在从productid中选择不同的q_products并检查另一个表productid中是否存在相同的q_product_apply_access,如果是,则检查{{1} }}与我们相同,如果q_product_apply_access.partnerid为0,则再次检查q_product_apply_access.apply_status是否在productid中。

3)它会执行类似的操作,如果productidList位于productid,则会再次检查。

我的优化想法是按照以下方式执行 - >

1)从我的productidList中的productidList中选择所有productids

2)检查这些q_products是否在表productidsq_product_apply_access中,如果是,则表示其后续条件已满足。

3)完成所有这些后,我会检查其中哪一个有q_product_aff_accessq_products.visibility IN (1,2,3)

我认为通过这种方式,我可以最小化表中的查找,并且我的查询将在productidList的最小子集中查询,该子集最多可包含20-30行。

这是我的代码,但我没有得到正确的答案。有人能告诉我怎么做吗?或者我应该如何在这里应用嵌套循环?

q_products.status=0

3 个答案:

答案 0 :(得分:1)

你问题的标题:

  

使用" AND"和"或"在SQL查询中

可能更准确地定义为:

  

将使用" AND"和/或" OR"语句可以帮助这个查询更快地运行吗?

而简短的回答是, .--优化可能需要在其他地方完成。

所以,答案很长:

经过一段时间的观察,这些要求已经成为'原始查询阻止逻辑JOIN加速任何事情。让它运行得更快的最好方法是利用被引用的表上的索引。我原来的答案是使用内部选择,但没有达到要求。通过要求,我的意思是必须从满足三个不同和不同标准的产品表中返回唯一产品列表。

也就是说,我会将原始查询重写为更具可读性的内容,使用JOIN语句和别名来提高可读性(注意缺少DISTINCT - {{1}确保所有3个结果集中的唯一记录

UNION

原始答案

因此,您遇到的问题有点困难,因为首先我很难绕过原始查询。也就是说,我使用内部选择作为SELECT p.productid FROM q_products p WHERE visibility = 1 AND status = 0 AND productid IN (productIdList) UNION SELECT p.productid FROM q_products p JOIN q_product_apply_access paa ON paa.productid = p.productid WHERE paa.partnerid = 'partnerid' AND paa.apply_status = 0 AND p.visibility = 3 AND p.status = 0 AND p.productid IN (productidList) UNION SELECT p.productid FROM q_products p JOIN q_product_aff_access paf ON paf.productid = p.productid WHERE paf.accid = 'accountid' AND p.visibility = 2 AND p.status = 0 AND p.productid IN (productidList) 表的连接,将可能的解决方案汇集在一起​​。我还没有测试过,所以让我知道结果如何:

q_products

答案 1 :(得分:0)

INDEX(visibility, status, productid)

使用原始UNION ALL

请提供SHOW CREATE TABLE;这可能会促使其他技术。

(编辑)

事实之后,你可以做到

ALTER TABLE q_products ADD INDEX(visibility, status, productid);

这需要一些时间,具体取决于桌子的大小。

INDEX通常比表格本身小得多。

索引是您防止慢查询的第一道防线。 (重写是第二个。)

q_products有多大?

答案 2 :(得分:0)

稍微重新格式化的原始查询是:

SELECT DISTINCT(q_products.productid)
  FROM q_products
 WHERE q_products.visibility = 1
   AND q_products.status = 0
   AND q_products.productid IN (productidList)
UNION  ALL 
SELECT DISTINCT(q_products.productid)
  FROM q_products, q_product_apply_access 
 WHERE q_products.productid = q_product_apply_access.productid 
   AND q_product_apply_access.partnerid = 'partnerid'
   AND q_product_apply_access.apply_status = 0 
   AND q_products.visibility = 3
   AND q_products.status = 0
   AND q_products.productid IN (productidList)
UNION  ALL
SELECT DISTINCT(q_products.productid)
  FROM q_products, q_product_aff_access 
 WHERE q_products.productid = q_product_aff_access.productid 
   AND q_product_aff_access.accid = 'accountid' 
   AND q_products.visibility = 2
   AND q_products.status = 0 
   AND q_products.productid IN (productidList)

您没有告诉我们除了visibility12以外3是否还有其他值,所以我们必须假设可以其他值(但请注意此答案下方的评论)。

我们可以看到有一些常见的子表达式限制来自q_productsstatus = 0productid IN (productidList)的行,其中并不清楚productidList真正的WITH pv AS (SELECT productid, visibility FROM q_products WHERE status = 0 AND visibility IN (1, 2, 3) -- or visibility >= 1 and visibility <= 3 AND productid IN (productidList) ) SELECT pv.productid FROM pv WHERE pv.visibility = 1 UNION ALL SELECT DISTINCT(pv.productid) FROM pv JOIN q_product_apply_access AS a ON pv.productid = a.productid WHERE pv.visibility = 3 AND a.apply_status = 0 AND a.partnerid = 'partnerid' UNION ALL SELECT DISTINCT(pv.productid) FROM pv JOIN q_product_aff_access AS f ON pv.productiond = f.productid WHERE pv.visibility = 2 AND f.accid = 'accountid' 是的,但我们可以假设它运作正常。

如果MySQL支持CTE(常用表表达式,又名WITH子句),那将非常有用:

visibility

由于MySQL还不支持CTE,因此您可能需要逐字写入CTE 3次,并希望优化器能够发现您正在做的事情。或者,由于所有备选方案都要更精确地过滤可见性,因此您可以将该术语包含在CTE的修改形式中(并避免明确选择SELECT pv.productid FROM (SELECT productid FROM q_products WHERE status = 0 AND visibility = 1 AND productid IN (productidList) ) AS pv UNION ALL SELECT DISTINCT(pv.productid) FROM (SELECT productid FROM q_products WHERE status = 0 AND visibility = 3 AND productid IN (productidList) ) AS pv JOIN q_product_apply_access AS a ON pv.productid = a.productid WHERE a.apply_status = 0 AND a.partnerid = 'partnerid' UNION ALL SELECT DISTINCT(pv.productid) FROM (SELECT productid FROM q_products WHERE status = 0 AND visibility = 2 AND productid IN (productidList) ) AS pv JOIN q_product_aff_access AS f ON pv.productiond = f.productid WHERE f.accid = 'accountid' )并将其写出三次 - 如下所示:

q_products

这应该产生相同的结果。很难确定它会更快。这可能取决于{{1}}的状态和可见性列是否有合适的索引。 UNION的第一个术语可以更简单地编写,但是这个表示与其他两个替代方案是统一的,这往往会使这些事情更清晰(对于人类阅读查询,也可能对查询优化器也是如此)。

与往常一样,研究实际的查询计划可能会帮助您改进。