Почему это не работает, чтобы удалить дубликаты - PullRequest
1 голос
/ 06 марта 2019

Я работал с MySQL, но сейчас я пытаюсь сделать то же самое с MS SQL (2016), но запрос не работает. У меня есть таблица «ТЕСТ», и я пытаюсь удалить дубликаты на основе соответствия столбцов «фамилия, имя».

Использование самого низкого значения идентификатора:

DELETE FROM TEST
WHERE lastname NOT IN (
  SELECT t.id FROM ( 
    SELECT MIN(PersonID) id
    FROM TEST
    GROUP BY lastname, firstname
  ) t
)

Столбцы: «PersonID», «LastName», «FirstName», «Address», «City»

.

Ошибка:

Сообщение 245, Уровень 16, Состояние 1, Строка 1 Преобразование не удалось при преобразовании значение varchar 'JOHN' для типа данных int.

Ответы [ 5 ]

1 голос
/ 06 марта 2019

Вы сравниваете фамилию с идентификатором, поэтому вы сообщили об ошибке "Преобразование не удалось при преобразовании значения varchar 'JOHN' в тип данных int" вместо этого попробуйте:

DELETE FROM TEST
WHERE PersonID NOT IN (
  SELECT t.id FROM ( 
    SELECT MIN(PersonID) id
    FROM TEST
    GROUP BY lastname, firstname
  ) t
)
1 голос
/ 06 марта 2019

Вы хотите сохранить строку с минимальным идентификатором, верно?Используйте EXISTS:

delete t from test t
where exists (
  select 1 from test
  where firstname = t.firstname and lastname = t.lastname
  and id < t.id
)
0 голосов
/ 06 марта 2019

Вы можете попробовать этот подход тоже:

DELETE T2 FROM ( 
    SELECT 
        MIN(PersonID) id
    FROM 
        TEST
    GROUP BY 
        lastname, firstname
  ) t
INNER JOIN TEST T2 ON t.id = T2.PersonID
0 голосов
/ 06 марта 2019

Вы можете попробовать преобразовать свой идентификатор в varchar / nvarchar, так как lastname является символом.Хотя вы можете дважды проверить, должны ли вы ссылаться на PersonID или фамилию.

DELETE FROM TEST
WHERE lastname NOT IN (
  SELECT CONVERT(VARCHAR(50),t.id) FROM ( 
    SELECT MIN(PersonID) id
    FROM TEST
    GROUP BY lastname, firstname
  ) t
)
0 голосов
/ 06 марта 2019

В SQL Server я рекомендую использовать оконные функции для этого:

with todelete as (
      select t.*,
             row_number() over (partition by firstname, lastname order by id) as seqnum
      from test t
     ) 
delete from todelete
    where seqnum > 1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...