我遇到了一个小问题,
这是一个演示查询
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
答案 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的某些部分。为某些类添加新的,更专业的方法,并使它们使用您手动制作的新查询。然后重构当前操作,以便它使用这些新方法。