Удалить повторяющиеся строки в таблице Oracle

другое решение:

$marray=array(....);
$options = array(
                "encoding" => "UTF-8",
                "output_type" => "xml", 
                "version" => "simple",
                "escaping" => array("non-ascii, on-print, markup")
                );
$xmlres = xmlrpc_encode_request('root', $marray, $options);
print($xmlres);
1
задан Marmite Bomber 20 January 2019 в 09:13
поделиться

4 ответа

Одним из способов является использование этого запроса:

SELECT principal,
    MAX(apellido) AS apellido,
    MAX(nombre) AS nombre 
FROM table_name
GROUP BY principal
HAVING COUNT(*) = 1
ORDER BY principal;
0
ответ дан Pham X. Bach 20 January 2019 в 09:13
поделиться

Вы можете использовать оконные функции. Логика будет такой:

select principal, apellido, nombre
from (select t.*, count(*) over (partition by principal) as cnt
      from t
     ) t
where cnt = 1;

Это вернет строки, где principal равно NULL; такие строки исключены в NOT EXISTS.

Однако, самый быстрый метод, если у вас есть первичный ключ и индекс на (principal, pk), это, вероятно,:

select principal, apellido, nombre
from t
where not exists (select 1
                  from t t2
                  where t2.principal = t.principal and t2.pk <> t.pk
                 );
0
ответ дан Gordon Linoff 20 January 2019 в 09:13
поделиться

Вы можете использовать агрегированную функцию 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, вы можете сделать дедупликация, т.е. вы позволяете одной из дублированных строк в результате и удаляете дубликаты.

Обратите внимание , что этот метод требует сортировки таблицы (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 в результате. Если это не требуется, необходимо добавить фильтр:

 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)
0
ответ дан Marmite Bomber 20 January 2019 в 09:13
поделиться

Иметь подзапрос, который возвращает значения PRINCIPAL, существующие более одного раза:

select *
from tablename
where PRINCIPAL not in (select PRINCIPAL from tablename
                        group by PRINCIPAL
                        having count(*) > 1)
0
ответ дан jarlh 20 January 2019 в 09:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: