Удалить почти дубликаты в таблице - PullRequest
1 голос
/ 08 ноября 2019

У меня есть таблица, где строки 1 и 2 почти повторяются - они имеют одинаковые значения, но в обратном порядке. Как я могу удалить эти дубликаты?

+--------+-------+
| COL_1  | COL_@ |
+--------+-------+
| a1     | b1    |
| b1     | a1    | <- same as 1stline but in reversed order, needs to be removed
| a2     | b2    |   
| a3     | b3    |
| b3     | a3    |<-- also is duplicate of string above, one of these 2str need                        
+--------+-------+     to be removed

expected result:
+--------+-------+
| COL_1  | COL_@ |
+--------+-------+
| b1     | a1    | 
| a2     | b2    |   
| a3     | b3    |                   
+--------+-------+

or
+--------+-------+
| COL_1  | COL_@ |
+--------+-------+
| a1     | b1    |
| a2     | b2    |   
| a3     | b3    |                    
+--------+-------+

Ответы [ 6 ]

1 голос
/ 08 ноября 2019

Вы имеете в виду, как это:

DELETE(
    select e.COL_@, f.COL_1
    from example as e
    join example as f on e.COL_@ = f.COL_1 and e.COL_@ < f.COL_1 )
0 голосов
/ 08 ноября 2019

Одно из возможных решений:

DELETE FROM T
  WHERE (COL_1, "COL_@") IN (SELECT COL_1, "COL_@"
                             FROM (SELECT ROWNUM AS RN, t1.COL_1, t1."COL_@"
                                     FROM T t1
                                     INNER JOIN T t2
                                       ON t2."COL_@" = t1.COL_1 AND
                                          t2.COL_1 = t1."COL_@")
                             WHERE RN / 2 <> TRUNC(RN / 2));

Обратите внимание, что COL_@ должно указываться в Oracle, поскольку @ не является допустимым символом в идентификаторе без кавычек.

dbfiddle здесь

0 голосов
/ 08 ноября 2019

Это не кажется таким сложным:

delete t
   where not (col1 < col2 or
              not exists (select 1
                          from t t2
                          where t2.col1 = t.col2 and
                                t2.col2 = t.col1
                         )
             );

Или:

delete t
   where col1 > col2 and
         exists (select 1
                 from t t2
                 where t2.col1 = t.col2 and
                       t2.col2 = t.col1
             );
0 голосов
/ 08 ноября 2019

Я думаю, что это немного сложно сделать с помощью запроса на удаление. Может быть, это нормально для вас, чтобы сначала иметь такой запрос выбора:

select A,B from (
                    select A,
                           B,
                           ROW_NUMBER() over (PARTITION BY ORA_HASH(A) * ORA_HASH(B) ORDER BY A) as RANK
                    FROM <your_table_name>
) where RANK = 1;

Вы можете сохранить результат этого запроса в виде новой таблицы с помощью CREATE TABLE AS SELECT ... И затем вы просто УДАЛИТЕ свою старую таблицу.

0 голосов
/ 08 ноября 2019

Если col_1 и col_ @ не могут быть нулевыми, вы можете использовать LEAST и GREATEST, чтобы сохранить по одной строке на комбинацию:

delete from tbl
where rowid not in
(
  select min(rowid) -- one rowid per combination to keep
  from tbl
  group by least(col_1, col_@), greatest(col_1, col_@)
);
0 голосов
/ 08 ноября 2019

Находится в Stackoveflow, кажется простым в реализации

DELETE FROM tbl a
USING  tbl b
WHERE  (a.x, a.y) = (b.y, b.x)
AND    a.y > a.x
...