如果您只有少量重复行,则使用就地更新/删除的替代方法将是首选。
所以先检查重复行数
with clean as (
select CUSTOMER_ID, TYPE, max(start_date) start_date_clean, max(end_date) end_date_clean
from tab group by CUSTOMER_ID, TYPE)
select tab.*, start_date_clean, end_date_clean
from tab join clean on tab.CUSTOMER_ID = clean.CUSTOMER_ID and tab.TYPE = clean.TYPE
where start_date != start_date_clean or end_date != end_date_clean
;
此查询将返回将要处理的所有行,即开始日期或结束日期不正确。
如果这个数字很大 - 按照其他答案建议的方式 - 复制表格并用副本替换原始表格。
如果**数字很小*,走update/delete方式:
update tab a
set a.START_DATE = (select max(b.START_DATE) from tab b where a.customer_id = b.customer_id and a.type = b.type),
a.END_DATE = (select max(b.END_DATE) from tab b where a.customer_id = b.customer_id and a.type = b.type)
where (a.customer_id, a.type) in
(
select tab.CUSTOMER_ID, tab.TYPE
from tab join
(select CUSTOMER_ID, TYPE, max(start_date) start_date_clean, max(end_date) end_date_clean
from tab group by CUSTOMER_ID, TYPE) clean
on tab.CUSTOMER_ID = clean.CUSTOMER_ID and tab.TYPE = clean.TYPE
where start_date != start_date_clean or end_date != end_date_clean);
这会将所有受影响行中的 start 和 end 日期更新为正确的值。
例子
CUSTOMER_ID START_DATE END_DATE TYPE
----------- ------------------- ------------------- ----------
1 01-01-2013 00:00:00 01-01-2016 00:00:00 1
1 01-01-2012 00:00:00 01-01-2018 00:00:00 1
1 01-01-2010 00:00:00 01-01-2017 00:00:00 1
2 01-01-2010 00:00:00 01-01-2018 00:00:00 1
3 01-01-2010 00:00:00 01-01-2018 00:00:00 1
更新为
CUSTOMER_ID START_DATE END_DATE TYPE
----------- ------------------- ------------------- ----------
1 01-01-2013 00:00:00 01-01-2018 00:00:00 1
1 01-01-2013 00:00:00 01-01-2018 00:00:00 1
1 01-01-2013 00:00:00 01-01-2018 00:00:00 1
2 01-01-2010 00:00:00 01-01-2018 00:00:00 1
3 01-01-2010 00:00:00 01-01-2018 00:00:00 1
在下一步中,必须删除重复的行。这使得下一次删除哪个用户ROW_NUMBER 来识别重复项:
delete from tab where rowid in
(select RID from (
select rowid rid,
row_number() over (partition by CUSTOMER_ID, TYPE order by null) rn
from tab)
where rn > 1)
;
您所看到的 - 蛮力 复制方法在查询中很简单,但会使表离线一段时间。您需要两倍的空间来执行它,并且需要一些时间。
update 方法更复杂,但没有维护窗口并且很快就完成了。