sql >> Base de Datos >  >> RDS >> Oracle

Declaración de actualización de Oracle con función de grupo

Tiene dos registros en cada tabla donde area es 01 , y debe configurarlos en diferentes valores para satisfacer la clave principal; no puede configurarlos en el valor máximo o mínimo de la segunda tabla, por lo que realmente no desea hacer ninguna agrupación.

No parece haber ningún otro orden entre registros con la misma area , así que asumiré que es arbitrario y no importa qué registro para cada area obtiene qué branch_code de la otra mesa. Si no es arbitrario, habría que especificar las reglas...

Una actualización correlacionada es complicada si necesita hacer coincidir un orden arbitrario dentro de un grupo de registros. Necesita alguna forma de identificar el orden de las filas, pero agregando un row_number() columna a las tablas originales para crear una vista en línea generará un error ORA-01732.

Sin embargo, puede usar el rowid de la tabla de destino pseudocolumna; solo tiene que hacer una unión adicional en la correlación para obtener el mismo valor junto con el nuevo branch_code . Algo como:

select bc.rid,
  bc.area,
  bc.branch_code,
  bc.branch_name,
  bc2.area,
  bc2.branch_code,
  bc2.branch_name
from (
  select bc.*,
    bc.rowid as rid,
    row_number() over (partition by bc.area order by bc.branch_code) as rn
  from branch_cp bc
) bc
join (
  select bc2.*,
    row_number() over (partition by bc2.area order by bc2.branch_code) as rn
  from branch_cp_2 bc2
) bc2
on bc2.area = bc.area
and bc2.rn = bc.rn;

Lo que te da:

RID                AREA  BRANCH_CODE BRANCH_NAME AREA  BRANCH_CODE BRANCH_NAME
------------------ ----- ----------- ----------- ----- ----------- -----------
AAAwy+AAEAAAA0DAAA 01    01          A           01    04          D           
AAAwy+AAEAAAA0DAAB 01    02          B           01    05          E           
AAAwy+AAEAAAA0DAAC 03    03          C           03    06          F           

Ahora en realidad no necesita todas esas columnas, solo necesita el rid (el branch_cp.rowid ) y el branch_cp_2.branch_code correlacionado .

Pero también solo desea actualizar cuando hay una coincidencia, para anular la anulación de las filas donde no hay valor en la otra tabla, por lo que tendría que repetir esa unión en exists subconsulta.

Es más sencillo hacer una merge :

merge into branch_cp bc
using (
  select bc.rid,
      bc2.branch_code
    from (
      select bc.*,
        bc.rowid as rid,
        row_number() over (partition by bc.area order by bc.branch_code) as rn
      from branch_cp bc
    ) bc
    join (
      select bc2.*,
        row_number() over (partition by bc2.area order by bc2.branch_code) as rn
      from branch_cp_2 bc2
    ) bc2
    on bc2.area = bc.area
    and bc2.rn = bc.rn
) bc2
on (bc.rowid = bc2.rid)
when matched then update set bc.branch_code = bc2.branch_code;

3 rows merged.

Tu mesa ahora tiene:

select * from branch_cp;

AREA  BRANCH_CODE BRANCH_NAME
----- ----------- -----------
01    04          A           
01    05          B           
03    06          C           

SQL Fiddle .