SQL: удалить только одну строку, если объединение возвращает несколько совпадений - PullRequest
0 голосов
/ 17 декабря 2018

У меня есть таблица SQL, которая выглядит следующим образом:

col1   col2
a      b
b      a
c      d
d      c
f      g

Как видите, есть строки, в которых оба столбца col1 и col2 инвертированы.Я имею в виду, что в первом ряду значения a и b находятся в обоих столбцах, а во втором ряду значения тоже есть, но наоборот.

Теперь я хочу удалить по одной строке каждой из этих пар.Мне все равно, какая сторона пары удаляется.Поэтому следует удалить либо строку 1 и строку 3, либо строку 2 и строку 4.

Результат должен выглядеть следующим образом:

col1   col2
a      b
c      d
f      g

или

col1   col2
b      a
d      c
f      g

IЭто достигается с помощью следующего запроса, который создает два искусственных столбца, которые содержат значения в отсортированном порядке, а затем применяет GROUP BY, но я предполагаю, что должно быть более привлекательное решение.

DELETE t1
FROM testtable t1
INNER JOIN (
    SELECT CASE WHEN col1 < col2 THEN col1 ELSE col2 END AS first, 
    CASE WHEN col1 < col2 THEN col2 ELSE col1 END AS second
    FROM testtable
    GROUP BY CASE WHEN col1 < col2 THEN col1 ELSE col2 END, CASE WHEN col1 < col2 THEN col2 ELSE col1 END
    ) t2 ON t2.first = t1.col1 AND t2.second = t1.col2

Ответы [ 3 ]

0 голосов
/ 17 декабря 2018

Я думаю, что вы можете упростить свой запрос, добавив условия в объединение:

    DELETE T1
    FROM #testable T1
        INNER JOIN #testable T2 ON T1.col1 = T2.col2 AND T1.col2 = T2.col1 AND T1.col1 > T1.col2
0 голосов
/ 17 декабря 2018

Предполагая, что фактических дубликатов нет, я бы сделал:

delete t from testtable t
    where col1 > col2 and
          exists (select 1
                  from testtable t2
                  where t2.col1 = t.col2 and t2.col2 = t.col1
                 );

То есть удалил строки, где col1 > col2, но только если в таблице уже есть "парная" строка.

0 голосов
/ 17 декабря 2018

Вы можете использовать exists & not exists:

select t.*
from testtable t 
where exists (select 1 
              from testtable t1 
              where t1.col1 > t.col1 and t1.col1 = t.col2
             ) or
      not exists (select 1 
                  from testtable t1 
                  where t1.col1 < t.col1 and t1.col1 = t.col2
                 );

Если вы хотите удалить ненужные записи, вы можете сделать:

delete t
from testtable t 
where not exists (select 1 
                  from testtable t1 
                  where t1.col1 > t.col1 and t1.col1 = t.col2
                 ) and
       exists (select 1 
               from testtable t1 
               where t1.col1 < t.col1 and t1.col1 = t.col2
              );
...