2013-06-28 158 views
3

我遇到了一個小問題,內部查詢,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個不同的表中獲取數據,檢查相同訂單類型的過去歷史記錄等,如果其結果是日期,我在第一個條件中獲取該日期。但是現在,如果條件計算爲10秒,則需要20秒,並且要重新執行10秒以返回結果。

有沒有什麼辦法可以減少這種?

,如果任何人有興趣看實際查詢http://pastebin.com/zqzbpEei

+1

+1因爲你沒有包含的代碼中的問題,那面牆。 –

+3

我的建議是重寫從相關子查詢「內部查詢」(他們現在)到'LEFT'加入你的主查詢的'FROM'子句。它可能會提高效率的原因有兩個: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的某些部分。爲某些類添加新的更專業的方法,並使其使用您手動製作的新查詢。然後重構您的當前操作,以便它使用這些新方法。