我想更新使用其他两列作为条件分组的列的值。假设表A(Char,b整数,c interger,d)和a列可以包含相同的对象名,所以我想用条件更新表:if column是一个值,b值是在两行row1中找到的: (A1,2,numbery)和row2:(A1,2,numberx)然后if:numberx,numbery> = 0-> AVG(第三列),elsif numberx,numbery< 0 THEN MIN其他MAX(即-3, 10→10)
--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
答案 0 :(得分: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
使用merge
在更新期间提供agregate值:
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