0

私が行う他のすべてのクエリは非常に高速ですが、mysql でサブクエリを使用するクエリが非常に遅くなり、最大で数分かかります。

サブクエリはおそらく悪い考えであることがわかったので、パフォーマンスに大きな影響を与えるサブクエリを使用する他のすべてのクエリで行ったように、このサブクエリを結合に変換したいと思いました。

私の他のクエリのほとんどは非常に単純ですが、これは私を夢中にさせます。

ここに例があります。

私はクライアントと請求書を持っています。クライアントには複数の請求書があります。紙幣には状態があります。また、請求書には「whatever」というパラメーターがあります。

「すべての請求書の状態が 1 または 2 で、請求書のパラメータが 2 でないすべてのクライアント」を更新する必要があります。

私はそれを行う方法を見つけることができなかったので、「状態1でも状態2でもない請求書を持たず、その請求書のパラメータが2ではないすべてのクライアント」である反転を使用しました

これらは、私が現在使用しているサブクエリを使用した 2 つのバリアントです。

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 状態で遅くなる

私は何時間も試しましたが、遅いサブクエリなしではこれを有用なものに変換できませんでした。結合または今よりも高速なものを使用してこれを行う方法を誰か教えてもらえますか?

アップデート

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
4

1 に答える 1

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
于 2012-04-27T01:47:42.333 に答える