Если вся строка дублируется и вы хотите удалить все копии, кроме одной, в SQL нет простого способа выбрать строки, которые вы хотите удалить, не используя системный адрес строки.
Используя таблицу PRICES
Ронниса в качестве примера, мы видим, что для B
есть три строки, которые являются точными дубликатами:
ID PRICE UPD_DATE
-- ----- -----------
A 7 10/04/2018
B 8 09/04/2018
B 8 09/04/2018
B 8 09/04/2018
C 7 04/04/2018
C 8 05/04/2018
C 9 06/04/2018
Хотя мы могли бы использовать что-то вроде
delete prices where id = 'B' and rownum <= 2;
это не очень хорошее решение, так как мы должны знать идентификаторы и количество и применять их к одному идентификатору за раз.
Мы можем удалить их без явного указания rowid с помощью PL / SQL:
declare
cursor c_prices is
select id, price
, row_number() over (partition by id order by upd_date desc) as seq
from prices
for update;
begin
for r in c_prices
loop
if r.seq > 1 then
delete prices where current of c_prices;
end if;
end loop;
end;
хотя, конечно, внутри синтаксиса where current of
используется rowid.
Использование rowid явно делает это намного проще:
delete prices where rowid in
( select lag(rowid) over (partition by id order by upd_date) from prices );
Находит все «предыдущие» строки в порядке даты и удаляет соответствующие строки. Последняя строка в каждом наборе не появится в этом списке и не будет удалена.