MYSQL查询减少条件中的内部查询

时间:2013-06-28 06:51:51

标签: mysql

我遇到了一个小问题,

这是一个演示查询

select 
    A.order_id, 
    if(
         A.production_date != '0000-00-00', 
         A.production_date,
         if(
              SOME INNER QUERY != '0000-00-00', 
              SOME INNER QUERY ,
              SOME OTHER INNER QUERY
           )
    ) as production_start_date
from
    orders A

基本上,假设SOME INNER QUERY花了10秒钟进行计算,从8个不同的表中获取数据,检查过去的历史记录是否有相同的订单类型等,如果结果是日期,我会获取该日期在第一个条件。但现在计算if条件需要20秒10秒,重新执行10秒钟以返回结果。

有什么方法可以减少这个吗?

如果有人有兴趣查看实际查询http://pastebin.com/zqzbpEei

1 个答案:

答案 0 :(得分:1)

假设您的查询看起来像这样(抱歉,我放弃了尝试找到实际查询):

IF(
    (SELECT aField FROM aTable WHERE bigCondition) != '0000-00-00',
    SELECT aField FROM aTable WHERE bigCondition,
    SELECT anotherField FROM anotherTable
)

您可以按如下方式重写它:

SELECT IF (
    someField != '0000-00-00',
    someField,
    SELECT anotherField FROM anotherTable
)
FROM aTable WHERE bigCondition

这样您只需计算一次bigCondition


这个查询确实非常难看。

您的主要问题似乎是IF()构造的滥用(以及滥用,大时间)。应该保留简单的条件和操作。这同样适用于逻辑运算符。不要对整个查询进行操作。例如,我在您的查询中看到这一点有几次出现:

IF(
    (SELECT v1.weekends FROM vendor v1 WHERE v1.vendor_id = A.vendor_id) IS NULL
       OR (SELECT v1.weekends FROM vendor v1 WHERE v1.vendor_id = A.vendor_id) = '',
    '6', -- by the way, why is this a string?! This is an integer, isn't it?
    (SELECT v1.weekends FROM vendor v1 WHERE v1.vendor_id = A.vendor_id)
)

这很糟糕。条件应直接移入SELECT。重写如下:

SELECT
    IF (v1.weekends IS NULL OR v1.weekends = '', 6, v1.weekends)
FROM vendor v1 WHERE v1.vendor_id = A.vendor_id

保存了两个SELECT。对包含查询的每个IF()执行此操作,我准备打赌您将以几个数量级的速度加快查询速度。

关于您当前的代码还有很多话要说。不幸的是,您可能需要重构ORM的某些部分。为某些类添加新的,更专业的方法,并使它们使用您手动制作的新查询。然后重构当前操作,以便它使用这些新方法。