Вы можете использовать агрегированную функцию COUNT
для удаления всех дублированных строк.
select PRINCIPAL, APELLIDO, NOMBRE,
count(*) over (partition by PRINCIPAL) dup_cnt
from tab
P A N DUP_CNT
- - - ----------
a b c 2
a l m 2
b c d 1
c d e 1
COUNT
считает строки для каждого уникального ключа, определенного в предложении PARTITION BY
.
Последний запрос выбирает только уникальные строки, то есть строки с DUP_CNT = 1
with dedup as (
select PRINCIPAL, APELLIDO, NOMBRE,
count(*) over (partition by PRINCIPAL) dup_cnt
from tab)
select PRINCIPAL, APELLIDO, NOMBRE
from dedup
where dup_cnt = 1
Примечание: используя ROW_NUMBER
вместо COUNT
вы можете выполнить дедупликацию, т. Е. Вы добавите одну из дублированных строк в результат и удалите дубликаты.
Обратите внимание , что этот метод требует sort таблицы (WINDOW SORT
), которая может быть тяжелой для больших таблиц. В этом случае метод, использующий NOT EXISTS
, может дать лучшую производительность, так как он преобразуется и выполняется как антихеш-соединение - HASH JOIN RIGHT ANTI
.
select principal, apellido, nombre
from tab t
where not exists
(select null
from tab
where principal = t.principal and rowid <> t.rowid
)
Необходимо соблюдать осторожность, если столбец дедупликации (principal
) имеет значение NULL. В отличие от первого решения с COUNT
, not exusts
оставляет все null
s в результате. Если это не требуется, необходимо добавить фильтр:
and t.principal is not NULL
Если у вас есть индекс для столбца pricipal
, оптимальный план выполнения выглядит следующим образом
--------------------------------------
| Id | Operation | Name |
--------------------------------------
| 0 | SELECT STATEMENT | |
|* 1 | HASH JOIN RIGHT ANTI | |
| 2 | INDEX FAST FULL SCAN| IDX |
|* 3 | TABLE ACCESS FULL | TAB |
--------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("PRINCIPAL"="T"."PRINCIPAL")
filter(ROWID<>"T".ROWID)
3 - filter("T"."PRINCIPAL" IS NOT NULL)