2012-04-27 99 views
0

我有一個查詢使用mysql中的子查詢得到非常緩慢,花費幾分鐘,而我做的所有其他查詢是非常快。MYSQL轉換速度較慢的子查詢(更快?)加入

因爲我發現subquerys最有可能是一個壞主意,所以我想將 這個子查詢轉換爲像我所有其他查詢那樣使用subquerys對性能產生重大影響的連接。

我的大部分其他查詢都非常簡單,但這個驅動我堅果。

這裏是一個例子。

我有客戶和賬單。客戶有多個賬單。票據有州。賬單有一個參數「無論」。

我需要更新 「裏所有的賬單都處於狀態1或2的所有客戶端和賬單無論參數不是2」

因爲我無法找到如何做到這一點我使用的轉化是 「所有客戶沒有賬單不處於狀態1,並且不處於狀態2,並且記錄任何參數不是2的賬單」

這些是我現在使用的subquerys的兩個變體,一個使用count和一個使用「不在」,但他們似乎同樣緩慢。

update client cl , bill bi 
set cl.parameter = "parameter1" 
where cl.parameter="parameter2" 
    and bi.whatever != "2" 
    and bi.client_id = cl.id 
    and (select count(cl.id) 
      from bill bi 
       where bi.client_id = cl.id 
        and bi.state!="state0" 
        and bi.state != "state1" 
     ) = 0; 

獲得MySQL中狀態慢「發送數據」

update client cl , bill bi 
set cl.parameter = "parameter1" 
    where cl.parameter="parameter2" 
     and bi.whatever != "2" 
     and bi.client_id = cl.id 
     and cl.id not in (select distinct cl.id 
           from bill bi 
            where bi.client_id = cl.id 
             and (bi.state!="state1" 
             and bi.state != "state2" 
          ) ; 

獲得MySQL中狀態慢「複製到臨時表」

我嘗試了好幾個小時,但我不能將它轉換爲沒有那麼慢的子查詢有用的東西。 任何人都可以給我一個想法如何使用連接或比現在更快的事情做到這一點?

UPDATE

由於DRapp,這將產生同樣的結果,是要快得多。對於我現在可以測試的內容,查詢時間可以縮短到幾秒鐘,這是幾分鐘前的事情。

select 
    c.id, 
    sum(if(b.State IN ("State1", "State2"), 1, 0)) as OkStatesCnt, 
    sum(if(b.State NOT IN ("State1", "State2") or b.whatever=2, 1, 0) ) as AnyOtherState 
from 
    client c 
    join bill b 
     ON c.id = b.client_id 
where 
    c.parameter = "parameter2" 
    group by 
     c.id 
    having 
     OkStatesCnt > 0 
    AND AnyOtherState = 0 

而且

UPDATE client cl, 
    (full select query from above) as PreQualified 
set cl.parameter = "parameter1" 
where cl.id = PreQualified.id 
+0

你能否確認下列內容......看起來你想更新所有在Bill表中存在的客戶......並且不在「狀態1」或「狀態2」中..作爲cl.id NOT IN的結果並查找Bill客戶端NOT State1或State1。 – DRapp 2012-04-27 01:39:52

+0

我想更新所有有賬單的客戶(賬單參考client.id),並且所有賬單都處於狀態1或狀態2,這意味着沒有更多的賬單處於任何其他狀態。 – dirk 2012-04-27 01:56:40

回答

0

要預先保證什麼客戶端將被包括在內,你可以運行在它自己的此查詢...

select 
     c.id, 
     sum(if(b.State IN ("State1", "State2"), 1, 0)) as OkStatesCnt, 
     sum(if(b.State IN ("State1", "State2"), 0, 1)) as AnyOtherState 
    from 
     client c 
     join bill b 
      ON c.id = b.client_id 
      AND b.whatever != "2" 
    where 
     c.parameter = "parameter2" 
       group by 
          c.id 
    having 
      OkStatesCnt > 0 
     AND AnyOtherState = 0 

如果在-事實是什麼你正在尋找,你可以執行到你的更新像

UPDATE client cl, 
     (full select query from above) as PreQualified 
    set cl.parameter = "parameter1" 
    where cl.id = PreQualified.id 
+0

嗯..這給了我所有的賬單都不是狀態1而不是狀態2的客戶。但我需要所有賬單都處於狀態1或狀態2的所有客戶,並且沒有賬單處於任何其他狀態。這就是爲什麼我在第一個查詢中使用了count的倒數,而在第二個查詢中使用了「not in」。 – dirk 2012-04-27 02:10:50

+0

@dirk,檢查修訂版。內部查詢執行OK狀態的計數和另一個AnyOther狀態。 HAVING將至少符合Ok State和AnyOther count = 0.只有問題我不知道如何應用是什麼時候「whatever!='2'」組件。你只想要!='2'條目考慮的計數,或只有那些State1/State2,但希望這給你一個跳躍,我可以幫你縮小這個結果。 – DRapp 2012-04-27 02:21:22

+0

啊,非常感謝你,這就是它。然而,我已經把這個b.whatever!= 2放到了sum(if(b.state NOT IN(「state1」,「state2」)或b.whatever = 2,1,0))中,作爲AnyOtherState。「完全是舊的查詢。我現在將更新我的問題以包含答案。再次感謝! – dirk 2012-04-27 05:33:52