2016-08-20 11 views
0

次の3つのクエリを使用して、別のテーブルの3つの異なるカラムの値に基づいてステータスを更新しています。別のテーブルの異なるカラムから同じカラムを更新する

UPDATE NUMBER_TABLE SET STATUS='X' WHERE STATUS='P' AND NUMBER IN 
      (SELECT NVL(CONTACT_NO,'XXXXXXXXXX') FROM TMP_NUMBER_FOUND WHERE STATUS='P'); 

UPDATE NUMBER_TABLE SET STATUS='X' WHERE STATUS='P' AND NUMBER IN 
      (SELECT NVL(HOME_NO,'XXXXXXXXXX') FROM TMP_NUMBER_FOUND WHERE STATUS='P'); 

UPDATE NUMBER_TABLE SET STATUS='X' WHERE STATUS='P' AND NUMBER IN 
      (SELECT NVL(WORK_NO,'XXXXXXXXXX') FROM TMP_NUMBER_FOUND WHERE STATUS='P'); 

すべての3つのクエリがフルテーブルスキャンを実行しています。誰かが私はこのような

UPDATE number_table n INNER JOIN tmp_number_found t 
           ON n.number = NVL(t.contact_no, 'XXXXXXXXXX') 
           OR n.number = NVL(t.home_no, 'XXXXXXXXXX') 
           OR n.number = NVL(t.work_no, 'XXXXXXXXXX') 
    SET n.status='X' 
WHERE n.status='P' 
    AND t.status='P' 
; 
+0

は 'NUMBER'が' 'XXXXXXXXXX''あるNUMBER_TABLE' 'で実際に行がありますか? –

答えて

1

何かが動作するはず示唆1

+0

ソリューションをありがとうございます。私はそれをより速くするためにこのクエリにヒントを使用することができます。 – Ashish

+0

わかりません(通常はありません)。 'NUMBER_TABLE.NUMBER'列にインデックスがありますか?また、NVLの処理に多大な時間がかかります。NUMBER_TABLEテーブルに 'NUMBER'の値が' XXXXXXXXXX 'という数多くの「数字」がありますか? – mathguy

+0

TMP_NUMBER_FOUNDでは、CONTACT_NOなどはNULLにすることができます。だから私はNVLを使ってNULL列をフィルタリングしました。私はXXXXXXXXXXを持っていません。 NUMBER_TABLE.NUMBERはPKの一部ですが、PKの2番目の列です。第一の助けになるだろうか? – Ashish

0

に3つのクエリをマージするより良い方法を提案することができます。

注:これらの3つのクエリを使用して更新すると言っています...そうではありません。あなたの質問は書かれたとおりには機能しません。 NUMBERは予約済みのOracleキーワードであるため、コンパイル・エラーが発生します。あなたが投稿するとき、あなたが言うことを非常に慎重にしてください。同じ理由で私が解決策として以下に提供しているクエリもうまくいかないでしょう。実際の列名を使用してください。

UPDATE NUMBER_TABLE n SET STATUS='X' WHERE STATUS='P' AND EXISTS 
    (SELECT 1 FROM TMP_NUMBER_FOUND t where n.NUMBER = NVL(t.CONTACT_NO, 'XXXXXXXXXX') 
             or n.NUMBER = NVL(t.HOME_NO , 'XXXXXXXXXX') 
             or n.NUMBER = NVL(t.WORK_NO , 'XXXXXXXXXX') 
    ) 
; 

(コメントを参照)OPからのさらなる情報に基づいてを追加しました。

OPは、データに'XXXXXXXXXX'に等しい数字がないという情報を共有しました。この場合、NVL(...)は不要で、時間が浪費されます。この場合の'XXXXXXXXXX'との比較は、NULLと比較するとTRUEを返さないため、NULLと比較する場合と同じになります。したがって:これらのNVLラッパーを削除してください、それらは遅さの大きな原因です。

これはさらに大きな利益、他の付属しています:彼らはまだなっていない場合は、列CONTACT_NOHOME_NOWORK_NOがインデックス化されなければならない、と彼らはNVL(...)に囲まれていない場合は、インデックスが実際に使用することができます。 NUMBERにも索引を付ける必要があります。 OPは、この列はPKの一部であるが、PKの最初の列ではなく、最初の列にする必要があるかどうかを尋ねた。答えはYESです。または、別の列が最初に残りたいという正当な理由がある場合(おそらく他のクエリがそれに依存している場合)、NUMBERは独自のインデックスを取得する必要があります。しかし、PKの最初のコラムにすることができれば十分です。

+0

動作しませんでした。エラーが発生しましたORA-00971 SETキーワードがありません – Ashish

1

あなたはアップデートでCASEを使用することができ、

UPDATE NUMBER_TABLE SET STATUS=(CASE when NUMBER IN 
      (SELECT NVL(CONTACT_NO,'XXXXXXXXXX') FROM TMP_NUMBER_FOUND WHERE STATUS='P') AND STATUS='P' then 'X' 
      when NUMBER IN 
      (SELECT NVL(HOME_NO,'XXXXXXXXXX') FROM TMP_NUMBER_FOUND WHERE STATUS='P') AND STATUS='P' then 'X' 
       WHEN NUMBER IN 
      (SELECT NVL(WORK_NO,'XXXXXXXXXX') FROM TMP_NUMBER_FOUND WHERE STATUS='P') AND STATUS='P' then 'X' ELSE STATUS END); 
+0

このクエリは、マッチした行のステータスを 'X'に設定していますが、 'P'値を終了するためにステータスをNULLに設定しています。 – Ashish

+0

は、 –

関連する問題