使用条件更新列-Oracle SQL

时间:2019-06-17 09:29:53

标签: sql oracle sql-merge

我有一张桌子:

u_a_id  d_c_s   c_nm    c_seq   r_c_p
1       908     Test1   1       20
10      908     Test1   1       21
11      908     Test1   1       12
12759   908     Test1   1       31
12759   908     Test1   1       32
12861   878     Test2   1       43
12861   878     Test2   1       44

我有SQL,可以找到重复的最小值r_c_p和最大值r_c_p:

select u_a_id, d_c_s, c_nm, c_seq, count(*) cnt, min(r_c_p) min_rcp, max(r_c_p) max_rcp
from table1
where c_nm not in ('VOID', 'WRONG')
group by u_a_id, d_c_s, c_nm, c_seq
having count(*) > 1;

我需要使用上述SQL的输出来更新d_c_s和c_nm,如下所示:

  • 对于min(r_c_p)-d_c_s = d_c_s + 12000且c_nm = c_nm || '-1'
  • 对于max(r_c_p)-d_c_s = d_c_s + 12000且c_nm = c_nm || '-2'

输出为:

u_a_id  d_c_s   c_nm       c_seq    r_c_p
1       908     Test1      1        20
10      908     Test1      1        21
11      908     Test1      1        12
12759   12908   Test1 - 1  1        31
12759   12908   Test1 - 2  1        32
12861   12878   Test2 - 1  1        43
12861   12878   Test2 - 2  1        44

DB提琴-Link

3 个答案:

答案 0 :(得分:1)

您必须将查询加入到表中并在CASE语句中应用条件:

select 
  t.u_a_id,
  case when g.u_a_id is null then t.d_c_s else 12000 + t.d_c_s end d_c_s,  
  case 
    when t.r_c_p = g.min_rcp then t.c_nm || '-1'
    when t.r_c_p = g.max_rcp then t.c_nm || '-2'
    else t.c_nm
  end c_nm,
  t.c_seq, 
  t.r_c_p
from table1 t left join (
  select u_a_id, d_c_s, c_nm, c_seq, count(*) cnt, min(r_c_p) min_rcp, max(r_c_p) max_rcp
  from table1
  where c_nm not in ('VOID', 'WRONG')
  group by u_a_id, d_c_s, c_nm, c_seq
  having count(*) > 1
) g on 
  g.u_a_id = t.u_a_id and g.d_c_s = t.d_c_s and g.c_nm = t.c_nm and g.c_seq = t.c_seq
  and t.r_c_p in (g.min_rcp, g.max_rcp)

请参见demo
结果:

> U_A_ID | D_C_S | C_NM    | C_SEQ | R_C_P
> -----: | ----: | :------ | ----: | ----:
>      1 |   908 | Test1   |     1 |    20
>     10 |   908 | Test1   |     1 |    21
>     11 |   908 | Test1   |     1 |    12
>  12759 | 12908 | Test1-1 |     1 |    31
>  12759 | 12908 | Test1-2 |     1 |    32
>  12861 | 12908 | Test1-1 |     1 |    43
>  12861 | 12908 | Test1-2 |     1 |    44

答案 1 :(得分:1)

您可以使用以下Merge语句。 不确定性能。但是您可以尝试一下,然后我们可以根据需要考虑进行任何性能调整。

MERGE INTO TABLE1 T1 
USING (
       SELECT
           U_A_ID,
           D_C_S,
           C_NM,
           C_SEQ,
           MIN(R_C_P) MIN_RCP,
           MAX(R_C_P) MAX_RCP
       FROM
           TABLE1
       WHERE
           C_NM NOT IN (
               'VOID',
               'WRONG'
           )
       GROUP BY
           U_A_ID,
           D_C_S,
           C_NM,
           C_SEQ
       HAVING
           COUNT(1) > 1
   )
T2 ON ( T1.U_A_ID = T2.U_A_ID
        AND T1.C_SEQ = T2.C_SEQ )
WHEN MATCHED THEN UPDATE SET T1.D_C_S = T1.D_C_S + 12000,
T1.C_NM = CASE
    WHEN T1.R_C_P = T2.MIN_RCP THEN T1.C_NM || '- 1'
    ELSE T1.C_NM || '- 2'
END
WHERE
    T1.D_C_S = T2.D_C_S
    AND T1.C_NM = T2.C_NM
    AND T1.U_A_ID = T2.U_A_ID

DB Fiddle demo

干杯!

答案 2 :(得分:0)

您可以使用merge

merge into table1 t1
    using (select tt1.u_a_id, tt1.d_c_s, t1.c_nm, tt1.c_seq, 
                  min(tt1.r_c_p) as min_r_c_p,
                  max(tt1.r_c_p) as max_r_c_p
           from table1 tt1
           where tt1.c_nm not in ('VOID', 'WRONG')
           group by tt1.u_a_id, tt1.d_c_s, t1.c_nm, tt1.c_seq
           having count(*) >= 2
          ) tt1
          on (tt1.u_a_id = t1.u_a_id and
              tt1.d_c_s = t1.d_c_s and
              tt1.c_nm = t1.c_nm and
              tt1.c_seq = t1.c_seq and
              tt1.r_c_p in (min_r_c_p, max_r_c_p)
             )
    when matched then
        set d_c_s = d_c_s + 12000,
            c_nm = (case when tt1.r_c_p = min_r_c_p then c_nm || '- 1'
                         when tt1.r_c_p = max_r_c_p then 
c_nm || '- 2'
                         else tt1.r_c_p
                    end);

为了提高性能,我建议在(u_a_id, d_c_s, c_nm, c_seq, r_c_p)上使用索引。