Обновить таблицу, используя значения другой таблицы - PullRequest
0 голосов
/ 14 ноября 2018

Я хочу очистить свою таблицу:

rid(PK)     rval
----------- ----------
10          test
11          Rtest
12          dummy
13          test
14          Rtest

, чтобы удалить дублирующиеся значения из столбца rval, поэтому я получаю:

rid(PK)     rval
----------- ----------
10          test
11          Rtest
12          dummy

Но у меня есть другаятаблица со связью внешнего ключа, в которой используются значения, которые я хочу удалить:

ruid       rid(FK)
---------- ----------
1          10
2          10
3          12
4          13
5          13
6          14
7          14

, поэтому перед удалением мне нужно обновить эту таблицу, чтобы использовать соответствующий rid, который я храню, например, обновлениеС 14 по 11;так что эта таблица будет иметь вид:

ruid       rid(FK)
---------- ----------
1          10
2          10
3          12
4          10
5          10
6          11
7          11

Как я могу это сделать?

1 Ответ

0 голосов
/ 14 ноября 2018

Вы можете использовать аналитический агрегат, чтобы получить наименьшее значение rid для каждого rval:

min(rid) over (partition by rval)

и используйте его в подзапросе, который объединяет две таблицы (которые я с воображением назвал t1 и t2, поскольку вы не дали их настоящие имена), чтобы вы могли видеть самые подходящие значения rid для каждой ruid

select t2.ruid, t2.rid, x.min_rid
from (
  select rid, min(rid) over (partition by rval) as min_rid from t1
) x
join t2 on t2.rid = x.rid;

      RUID        RID    MIN_RID
---------- ---------- ----------
         1         10         10
         2         10         10
         3         12         12
         4         13         10
         5         13         10
         6         14         11
         7         14         11

Затем вы можете использовать это в операторе слияния:

merge into t2
using (
  select t2.ruid, t2.rid, x.min_rid
  from (
    select rid, min(rid) over (partition by rval) as min_rid from t1
  ) x
  join t2 on t2.rid = x.rid
) y
on (t2.ruid = y.ruid)
when matched then update set t2.rid = y.min_rid
where t2.rid != y.min_rid;

4 rows merged.

select * from t2;

      RUID        RID
---------- ----------
         1         10
         2         10
         3         12
         4         10
         5         10
         6         11
         7         11

Как только вы это сделаете, вы можете удалить избыточные значения PK:

delete from t1
where exists (select * from t1 x where x.rval = t1.rval and x.rid < t1.rid);

2 rows deleted.

select * from t1;

       RID RVAL 
---------- -----
        10 test 
        11 Rtest
        12 dummy

Id ruid не является уникальным, и нет другого уникального ключа, который вы можете включить в оператор, тогда вы не сможете использовать слияние - вы не можете ссылаться на rid в предложении on поскольку это столбец, который вы обновляете.

Вместо этого вы можете сделать соответствующее обновление:

update t2
set rid = (
  select min_rid
  from (
    select rid, min(rid) over (partition by rval) as min_rid from t1
  ) x
  where x.rid = t2.rid
);

Это обновит каждую строку; если у вас много данных и / или небольшая часть должна быть изменена, вы можете добавить фильтр, чтобы обновлять только эти:

update t2
set rid = (
  select min_rid
  from (
    select rid, min(rid) over (partition by rval) as min_rid from t1
  ) x
  where x.rid = t2.rid
)
where rid != (
  select min_rid
  from (
    select rid, min(rid) over (partition by rval) as min_rid from t1
  ) x
  where x.rid = t2.rid
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...