2011-04-05 14 views
9

私のUPDATEステートメントは、の線に沿って行く:SQL - CASE文で更新すると、同じCASEを何度も繰り返す必要がありますか?

UPDATE customer 
SET forenames=ot.forenames, 
    surname = 

CASE WHEN ot.safeplace IS NULL 
THEN 'test SAFEPLACE IS NULL' 
ELSE 'test Safeplace IS NOT NULL' 
END, 

    middlename = 

CASE WHEN ot.safeplace IS NULL 
THEN 'test2 SAFEPLACE IS NULL' 
ELSE 'test2 Safeplace IS NOT NULL' 
END, 

FROM order_transaction ot 

WHERE customer.custid = ot.custid 
AND ot.trans_orderid = 5678 
AND customer.custid = 1234 

上記の作品を。基本的には、別のテーブルのフィールドがNULLかどうかをチェックし、それに応じて顧客の "姓"と "middlename"を更新します。上記のように、私は同じCASEステートメントを2回繰り返しました。私の質問です - 私は1回だけCASEステートメントを指定する方法はありますか?

特定の条件に基づいて10個のフィールドを更新したい場合、10個の同様のCASE条件を含める必要がありますか?あるいは、WHEN/ELSE句内に1つのCASEと10個のフィールド更新を持つようにSQLを改善することはできますか?

(私はPostgreSQL 8.2データベースを使用していますが、上記は標準SQLと思われます)。

多くのおかげで、 リシ

答えて

3

あなたが同じクエリレベルでCASEを実行したい場合、あなたはGROUP BY句で計算列を繰り返すのと同じように、CASEを繰り返す必要があります。あなたのサンプルクエリがすべてであなたが何をしたいのか明らかにしない

は、あなたが実際には同じ値(固定テキスト)へすべての記録だけでなく、レコードごとにすべての列を更新しています。質問をより適切にするために更新した場合は、おそらくもっと良い答えがあります。


しかし、あなたは、次のクエリを使用することができ、正確なケースをコピーするために複数回(2そして、もっとたくさん)が必要な場合は、今のところ、あなたの特定のクエリのために、あなたは、この

UPDATE customer 
SET forenames=ot.forenames, 
    surname = fixedText, 
    middlename = fixedText  
FROM (select o.*, CASE 
     WHEN safeplace IS NULL 
     THEN 'test2 SAFEPLACE IS NULL' 
     ELSE 'test2 Safeplace IS NOT NULL' 
     END fixedText 
     from order_transaction o) ot 
WHERE customer.custid = ot.custid 
AND ot.trans_orderid = 5678 
AND customer.custid = 1234 
+0

本当に最高のリチャードRichard。選択したテーブルが最初にテーブルをスキャンして結果を追加した後、それをフィルタリングします。 –

+1

@Dumitrescu Bogdan /私はそうは思わない。 PostgreSQLはサブクエリにフィルタを適用するためにクエリを展開するので、定義済みの(計算された)カラムを使用する能力は保持されます – RichardTheKiwi

+0

OPの構文は標準SQLではありません(SQL標準は国際標準であり、 'ANSI'は 'American'の略ですので、ここでは「ISO準拠のSQL」がより適切でしょう:) – onedaywhen

0

のようなものを使用することができます。しかし、実際には、testとtest2ではなく、ケースをコピーする必要があります(これは全く同じケースではありません)。明らかに、test/test 2のようなテキストを連結する必要がある場合や、結果に何があったとしても、select文でそれを行うことができます。 ex:surname = 'test' + st.resultだから、いくつかの 'ハッキング'を行う可能性があります。

UPDATE customer 
SET forenames=ot.forenames, 
    surname = st.result, 
    middlename = st.result 

FROM order_transaction ot 
JOIN (select 1 as ID,'test SAFEPLACE IS NULL' as result 
     union 
     select 2,'test SAFEPLACE IS NULL') st on case when ot.safeplace is null then 1 else 2 end = st.id 

WHERE customer.custid = ot.custid 
AND ot.trans_orderid = 5678 
AND customer.custid = 1234 
7

私は実際には、標準のSQL

がないです上記と信じています。標準SQLにはUPDATE..FROMという構文がありません。代わりに、SET節ごとにスカラーサブクエリを使用し、EXISTSに別のスカラーサブクエリを使用する必要があります。したがって、標準構文はさらに繰り返します。

UPDATE customer 
    SET forenames = (
        SELECT ot.forenames 
         FROM order_transaction AS ot 
        WHERE customer.custid = ot.custid 
          AND ot.trans_orderid = 5678 
        ), 
     surname = (
        SELECT CASE 
          WHEN ot.safeplace IS NULL 
           THEN 'test SAFEPLACE IS NULL' 
          ELSE 'test Safeplace IS NOT NULL' 
         END 
        FROM order_transaction AS ot 
        WHERE customer.custid = ot.custid 
         AND ot.trans_orderid = 5678 
       ), 
     middlename = (
        SELECT CASE 
           WHEN ot.safeplace IS NULL 
            THEN 'test SAFEPLACE IS NULL' 
           ELSE 'test Safeplace IS NOT NULL' 
          END 
         FROM order_transaction AS ot 
         WHERE customer.custid = ot.custid 
          AND ot.trans_orderid = 5678 
        ) 
WHERE customer.custid = 1234 
     AND EXISTS (
        SELECT * 
        FROM order_transaction AS ot 
        WHERE customer.custid = ot.custid 
          AND ot.trans_orderid = 5678 
       ); 

構文は、繰り返しになりますが、良いオプティマイザは反復を認識し、それに応じて最適化することができるはずです。現行バージョンのSQL製品が実際にこれを最適化するかどうかは、もちろん別の問題です。しかし、これを考慮してください:あなたのSQL製品が標準構文をサポートしていても、実際にそれを適切に最適化していない場合は、「サポート」は価値がありますか?

標準SQLを使用する場合は(実際にはIMO :)、よりコンパクトな構文が必要な場合はMERGEまたはMERGE (SQL)などをご覧ください。

MERGE INTO customer 
    USING (
      SELECT ot.custid, ot.forenames, 
       CASE 
        WHEN ot.safeplace IS NULL 
         THEN 'test SAFEPLACE IS NULL' 
        ELSE 'test Safeplace IS NOT NULL' 
        END 
      FROM order_transaction AS ot 
      WHERE ot.trans_orderid = 5678 
     ) AS source (custid, forenames, safeplace_narrative) 
    ON customer.custid = source.custid 
     AND customer.custid = 1234 
WHEN MATCHED THEN 
    UPDATE 
     SET forenames = source.forenames, 
      surname = source.safeplace_narrative, 
      middlename = source.safeplace_narrative; 
+0

@リチャード・エイカ・サイバースキー:もっとコンパクトであることを示すマージ例を追加しました。標準SQLのままです。 – onedaywhen

関連する問題