2011-02-08 11 views
0

2つの他の列を基準としてグループ化された列の値を更新したいとします。テーブルA(Char、b整数、c interger、d)を仮定し、a列は同じオブジェクト名を含むことができるので、条件を使ってテーブルを更新したい:列の値とb値が2行row1にある場合: (A1,2、numbery)およびrow2:(A1,2、numberx)then:numberx、numbery> = 0-> AVG(3列目)、elsif numberx、numbery < 0 THEN MIN else MAX →10)。plsql- UPDATE-SETのAVG、MAX関数を使用

--a--|--b--|--c--|--d-- desired TABLE update (A1,A2) --a--|--b--|--c--|--d-- 
A1  2  10 b          A1  2 "15" b  
A2  7  -9 bc         A2  7  "4" bc   
A3  7  12 fg         A3  7  12 fg 
A1  2  20 sa         A1  2 "15" sa 
A2  7  4 sa         A2  7 "4"  sa 
+1

少なくとも試してみてくださいそれをもっと読みやすくするために。 –

+1

それは何か、奇妙な代数のようなものですか? –

答えて

1

表やサンプルデータを作成します。

SQL> create table t (a varchar2(20) not null 
    2  , b number(38) not null 
    3  , c number(38) not null 
    4  , d varchar2(20) not null); 

Table created. 

SQL> insert into t values ('A1', 2, 10, 'b'); 

1 row created. 

SQL> insert into t values ('A2', 7, -9, 'bc'); 

1 row created. 

SQL> insert into t values ('A3', 7, 12, 'fg'); 

1 row created. 

SQL> insert into t values ('A1', 2, 20, 'sa'); 

1 row created. 

SQL> insert into t values ('A2', 7, 4, 'sa'); 

1 row created. 

SQL> commit; 

Commit complete. 

更新を把握しやすくするために、私はそれらを理解し、望ましい結果を与えるクエリを作成します。ソリューションの(一部ではありません、の一部だけを解決)

SQL> select t.a, t.b 
    2  , case when agg_t.min_c >= 0 then avg_c -- all values of c are >= 0 
    3   when agg_t.max_c < 0 then min_c -- all values of c are < 0 
    4   else agg_t.max_c end as c 
    5  , t.d 
    6 from (select a, b, min(c) as min_c 
    7   , max(c) as max_c , avg(c) as avg_c 
    8  from t 
    9  group by a, b) agg_t 
10 inner join t on agg_t.a = t.a and agg_t.b = t.b 
11/

A        B   C D 
-------------------- ---------- ---------- -------------------- 
A3       7   12 fg 
A1       2   15 sa 
A2       7   4 bc 
A2       7   4 sa 
A1       2   15 b 
更新中にagregate値利用できるようにする

使用merge

SQL> merge into T dest 
    2 using (select a, b, min(c) as min_c 
    3   , max(c) as max_c , avg(c) as avg_c 
    4  from t 
    5  group by a, b) src 
    6 on (dest.a = src.a and dest.b = src.b) 
    7 when matched then update 
    8  set c = case when src.min_c >= 0 then avg_c -- all values of c are >= 0 
    9   when src.max_c < 0 then min_c -- all values of c are < 0 
10   else src.max_c end 
11/

5 rows merged. 

SQL> select * from t; 

A        B   C D 
-------------------- ---------- ---------- -------------------- 
A1       2   15 b 
A2       7   4 bc 
A3       7   12 fg 
A1       2   15 sa 
A2       7   4 sa 

ロールバックは、テストデータを初期する:

SQL> rollback; 

Rollback complete. 

このクエリは、変更が実際にロックを減らし、行われていない行を更新元に戻すとやり直しません。

SQL> merge into T dest 
    2 using (select a, b 
    3   , case when min_c >= 0 then avg_c -- all values of c are >= 0 
    4    when max_c < 0 then min_c -- all values of c are < 0 
    5    else max_c end as new_c 
    6  from (select a, b, min(c) as min_c 
    7    , max(c) as max_c , avg(c) as avg_c 
    8   from t 
    9   group by a, b)) src 
10 on (dest.a = src.a and dest.b = src.b) 
11 when matched then update set c = new_c 
12 where c <> new_c 
13 or (c is null and new_c is not null) 
14 or (c is not null and new_c is null) 
15/

3 rows merged. 

SQL> 
SQL> select * from t; 

A        B   C D 
-------------------- ---------- ---------- -------------------- 
A1       2   15 b 
A2       7   4 bc 
A3       7   12 fg 
A1       2   15 sa 
A2       7   4 sa 
関連する問題