0

アイテムのグループ化を表すテーブル ( table1 ) と、アイテム自体を表す別のテーブル ( table2 ) があります。
table1.id は table2 への外部キーであり、table1 のすべてのレコードで、その特定のレコードに関連付けられた table2 のレコードの総数やさまざまなフィールドの合計などの情報も収集して、グループ化と内容の要約を表示できるようにしますtable2 をクエリする必要はありません。
通常、table2 の項目は一度に 1 つずつ追加/削除されるため、table1 を更新して table2 の変更を反映します。

新しい要件が発生しました。グループ内の選択されたアイテムを新しいグループに移動する必要があります。私はそれを3段階の操作と考えました:

  1. table1 に新しいグループを作成する
  2. table2 で選択されたレコードを更新して、table1 で新しく作成されたレコードを指すようにします

3 番目のステップは、レコード数 / 表示する必要がある他のフィールドの合計をグループから減算し、それらを新しいグループに追加することです。このデータは、新しいグループに関連付けられた項目について table2 をクエリするだけで見つけることができます。

機能する次のステートメントを思いつきました。

update table1 t1 set 
countitems = ( 
    case t1.id 
      when 1 then t1.countitems - ( select count( t2.id ) from table2 t2 where t2.id = 2 )
      when 2 then ( select count( t2.id ) from table2 t2 where t2.id = 2 )
    end
), 
sumitems = (
    case t1.id
      when 1 then t1.sumitems - ( select sum( t2.num ) from table2 t2 where t2.id = 2 )
      when 2 then ( select sum( t2.num ) from table2 t2 where t2.id = 2 )
    end
)
where t1.id in( 1, 2 );

毎回サブクエリを繰り返さずにステートメントを書き直す方法はありますか?

ありがとう
ピエロ

4

1 に答える 1

0

ROWIDでカーソルと一括収集更新ステートメントを使用できます。このようにして、目的の結果で結合クエリを記述し、それらの値でテーブルを更新することができます。私はいつもこの機能を使い、毎回微調整をしています。

declare
    cursor cur_cur
    IS
    select ti.rowid     row_id
    ,      count(t2.id) countitems
    ,      sum(t2.num)  numitems
    from   table t1
    join   table t2 on t1.id = t2.t1_id
    order by row_id
    ;

    type type_rowid_array is table of rowid index by binary_integer;
    type type_countitems_array is table of table1.countitems%type;
    type type_numitems_array is table of table1.numitems%type;

    arr_rowid type_rowid_array;
    arr_countitems type_countitems_array;
    arr_numitems type_numitems_array;

    v_commit_size number := 10000;

begin
    open cur_cur;

    loop
        fetch cur_cur bulk collect into arr_rowid, arr_countitems, arr_numitems limit v_commit_size;

        forall i in arr_rowid.first .. arr_rowid.last
            update table1 tab
            SET    tab.countitems = arr_countitems(i)
            ,      tab.numitems = arr_numitems(i)
            where  tab.rowid = arr_rowid(i)
            ;

        commit;
        exit when cur_cur%notfound;

    end loop;

    close cur_cur;
    commit;

exception
  when others
    then rollback;
         raise_application_error(-20000, 'ERROR updating table1(countitems,numitems) - '||sqlerrm);

end;
于 2012-09-18T11:32:02.803 に答える