plsql-在UPDATE-SET中使用AVG,MAX函数

时间:2011-02-08 12:18:19

标签: plsql

我想更新使用其他两列作为条件分组的列的值。假设表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

1 个答案:

答案 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