Как зафиксировать / выполнить удаление построчно в SQL (MSSQL) - PullRequest
0 голосов
/ 24 октября 2011

У меня есть простая таблица, но длинная (несколько миллионов или строк). Таблица содержит много парных строк, которые мне нужно удалить. Данные строки не различаются! Есть одиночные строки (у которых нет парной строки) Пары таблиц определяются перекрестной информацией в двух столбцах, соединенных с третьим столбцом. Я хотел бы иметь только одну строку каждого идентификатора данных. Поэтому мне нужно, чтобы myTable немедленно уменьшался при выполнении условия. Я попробовал:

myIndexColumn = Column1 + Column2 + Column3
myReversedIndexColumn = Column2 + Column1 + Column3

CREATE NONCLUSTERED INDEX myIndex1 ON myDB.dbo.myTable (
  myIndexColumn ASC
)
CREATE NONCLUSTERED INDEX myIndex2 ON myDB.dbo.myTable (
  myReversedIndexColumn ASC
)

DELETE FROM myDB.dbo.myTable
WHERE myIndexColumn in (SELECT myReversedIndex FROM myDB.dbo.myTable)

Проблема в том, что обе парные данные удаляются вместо того, чтобы оставить одну строку данных.

Очевидно, это потому, что DELETE фиксирует изменения только после выполнения всей транзакции.

Если бы я мог убедить редакцию MS SQL 2008 R2 Express зафиксировать DELETE при выполнении условия, предложение SELECT вывело бы более короткий список в каждом тесте строки для удаления.

Как мне это сделать?

1 Ответ

1 голос
/ 24 октября 2011

К не удалить случаи, когда column1 = column2

DELETE FROM myDB.dbo.myTable
WHERE myIndexColumn in (SELECT myReversedIndex FROM myDB.dbo.myTable)
  AND column1 <> column2

Для удаления column1 = column2

;with cte as
(
    select *,
        row_number() over (
                partition by Column1 + Column2 + Column3
                order by (SELECT 1)
                ) rn
    from yourtable
    where column1 = column2
)
delete cte where rn > 1

CTE можно использовать для удаления всех дубликатовтоже

;with cte as
(
    select *,
        row_number() over (
                partition by 
                      CASE WHEN Column1 > Column2 THEN Column2 ELSE Column1 END + 
                      CASE WHEN Column1 > Column2 THEN Column1 ELSE Column2 END + 
                      Column3
                order by (SELECT 1)
                ) rn
    from yourtable
)
delete cte where rn > 1
...