2011-09-09 29 views
2

ここでは取引があります。私はデータを持つテーブルを持っています。私は特定のフィールドに基づいて行の発生をフィールドに設定する必要があります。私は1つの列を持つことができる、私は10を持つことがあります。私はその番号を設定する必要があります。私はrownumber()を使用して、選択肢の中で何が何であるかを判断しています。しかし、テーブルの更新は問題がありました。私はジョイントを試しました。それはtablenameで、それからselect、then updateです。何も働いていません。複数の行を持つOracleのrow_number()を使用した更新

このコード:

update Rptdata 
SET c98 = (SELECT R from 
       (select rs1.c1, rs1.c5,rs1.c3, 
       row_number() over(partition by rs1.c1,0, rs1.c5,rs1.c3 order by rs1.c1,rs1.c5,rs1.c3 desc) as R 
       from Rptdata rs1 
       where rs1.c1 = c1 
       and rs1.c5 = c5 
       and rs1.c3 = c3 
     --  and rs1.c6 = c6 
     --  and rs1.c7 = c7 
     --  and rs1.c8 = c8 
     --  and rs1.c9 = c9 
       and rs1.program_name = 'INTERNAL' 
       AND rs1.program_id=030911 
       AND (rs1.c6 IS NULL 
       or rs1.c8 IS NULL 
       or rs1.c9 IS NULL) 
       and rs1.c28 IS NULL 
       ) 
     ) 
WHERE program_name = 'INTERNAL' 
AND program_id=030911 
AND (c6 IS NULL 
or c8 IS NULL 
or c9 IS NULL) 
and c28 IS NULL 

はエラーORA-01427を産生する:単一行のサブクエリは、複数の行を返します。それは私が望むものだと思います。私はコメントアウトを外して - rs1.c6 = c6 そしてそれは私に187行(これは正しい)を更新したことを伝えます。私はコミットし、それらの187の行に選択を実行し、c98には何もありません。

答えて

4

row_numberが必要な結果を得るためにサブクエリ全体を1つのセットとして処理する必要がありますが、そのセットを単一のレコードに減らす必要があるという問題があります各行を更新します。これはupdateと厳密には可能ですが、それは(あなたが10グラムを使用していると仮定して)このシナリオでmergeを使用して多くの方が簡単です:

ちなみに
MERGE INTO rptdata rp 
USING  (SELECT ROW_NUMBER() OVER (PARTITION BY rs1.c1, 0, rs1.c5, rs1.c3 
             ORDER BY rs1.c1, rs1.c5, rs1.c3 DESC) AS r 
      FROM rptdata rs1 
      WHERE rs1.program_name = 'INTERNAL' 
       AND rs1.program_id = 030911 
       AND (rs1.c6 IS NULL OR rs1.c8 IS NULL OR rs1.c9 IS NULL) 
       AND rs1.c28 IS NULL) rs 
ON   (rs.c1 = rp.c1 AND rs.c5 = rp.c5 AND rs.c3 = rp.c3) 
WHEN MATCHED THEN 
    UPDATE SET 
     c98 = rs.r 
     WHERE  program_name = 'INTERNAL' 
      AND program_id = 030911 
      AND (c6 IS NULL OR c8 IS NULL OR c9 IS NULL) 
      AND c28 IS NULL 

、あなたが提供するクエリはそこまでではありませんオフ。上で述べたように、row_numberでセット全体を取得し、更新する各行に必要な個々のレコードをフィルタリングする必要があります。これを行うには、結合条件を外部クエリに移動する必要があります。

UPDATE rptdata 
SET c98 = 
      (SELECT r 
      FROM (SELECT rs1.c1, 
          rs1.c5, 
          rs1.c3, 
          ROW_NUMBER() OVER (PARTITION BY rs1.c1, 0, rs1.c5, rs1.c3 
              ORDER BY rs1.c1, rs1.c5, rs1.c3 DESC) 
          AS r 
        FROM rptdata rs1 
        WHERE rs1.program_name = 'INTERNAL' 
         AND rs1.program_id = 030911 
         AND (rs1.c6 IS NULL OR rs1.c8 IS NULL OR rs1.c9 IS NULL) 
         AND rs1.c28 IS NULL) 
      WHERE rs1.c1 = c1 AND rs1.c5 = c5 AND rs1.c3 = c3) 
WHERE program_name = 'INTERNAL' 
    AND program_id = 030911 
    AND (c6 IS NULL OR c8 IS NULL OR c9 IS NULL) 
    AND c28 IS NULL 
関連する問題