Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Удаление одинаковых записей  [new]
:(
Guest
Добрый вечер форумчане!

Знаю, что это, наверное, уже миллионный вопрос на эту тему, но все таки:
Как удалить из таблицы дубликаты ВКЛЮЧАЯ оригинал (т.е. если 2 строки одинаковы то удалить обе) и желательно без перечисления полей, так как их количество не известно? Столбца идентификатора нет, заглядывал в ФАК, но там не тот случай:(

Заранее спасибо за ответы!
14 апр 15, 16:38    [17514072]     Ответить | Цитировать Сообщить модератору
 Re: Удаление одинаковых записей  [new]
iap
Member

Откуда: Москва
Сообщений: 47198
Без перечисления полей не получится.
Потому что невозможно провести проверку
наличия другой записи с теми же значениями полей.
Сама-то запись всегда будет вылезать и мешать при попытке такой проверки.
А ключа нет. Да если бы и был, он как раз и не давал бы понять,
что записи на самом деле одинаковые.
14 апр 15, 16:56    [17514157]     Ответить | Цитировать Сообщить модератору
 Re: Удаление одинаковых записей  [new]
Gviber
Member

Откуда:
Сообщений: 124
Какой sql server?
14 апр 15, 16:56    [17514158]     Ответить | Цитировать Сообщить модератору
 Re: Удаление одинаковых записей  [new]
Gviber
Member

Откуда:
Сообщений: 124
Попробуйте так:
declare @TableName varchar(150)= 'dbo.TABLE' ,@SQL nvarchar(max)=''
SELECT @SQL = 'with S as (SELECT RANK() OVER( order by ' +REPLACE(
(
	SELECT COLUMN_NAME AS 'data()'
	FROM INFORMATION_SCHEMA.COLUMNS
	WHERE TABLE_SCHEMA+'.'+TABLE_NAME =@TableName
	ORDER BY ORDINAL_POSITION
	FOR XML PATH(''))
,' ',', ') + ') rnk FROM '+ @TableName +') 
delete from S where rnk in
(
	select rnk from S group by rnk having  count (*)>1
)
'
EXEC sp_executeSQL  @SQL

Забавный скрипт получился. Не проверял, но в целом должно работать.
14 апр 15, 17:02    [17514190]     Ответить | Цитировать Сообщить модератору
 Re: Удаление одинаковых записей  [new]
Gviber
Member

Откуда:
Сообщений: 124
Проверил - работает =)

Нужно указать правильную таблицу @TableName (обязательно со схемой) + count (*)>1 возможно нужно заменить на count (*)=2 (удалять только если запись повторяется два раза)
14 апр 15, 17:08    [17514218]     Ответить | Цитировать Сообщить модератору
 Re: Удаление одинаковых записей  [new]
:(
Guest
Gviber,

Странно, но не работает. Таблицу указываю верную, ошибок не выдает, просто выводится эта же таблица. Есть идеи почему так?
Версия:
Microsoft SQL Server 2012 - 11.0.2100.60 (X64)
Feb 10 2012 19:39:15
Copyright (c) Microsoft Corporation
Express Edition (64-bit) on Windows NT 6.1 <X64> (Build 7601: Service Pack 1)
14 апр 15, 22:37    [17515474]     Ответить | Цитировать Сообщить модератору
 Re: Удаление одинаковых записей  [new]
:(
Guest
Ой ой, понял в чем ошибка, не правильно вводил значение @TableName
Можно тогда узнать почему нужно вводить значение с 'dbo. ...'? Почему нельзя просто указать имя таблицы?
14 апр 15, 22:49    [17515517]     Ответить | Цитировать Сообщить модератору
 Re: Удаление одинаковых записей  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 32173
:(
Можно тогда узнать почему нужно вводить значение с 'dbo. ...'? Почему нельзя просто указать имя таблицы?
А вы прочтите скрипт, а не просто выполняйте :-)
Выполнять чужие скрипты без их чтения опасно для здоровья сервера и своего :-)
14 апр 15, 23:00    [17515554]     Ответить | Цитировать Сообщить модератору
 Re: Удаление одинаковых записей  [new]
:(
Guest
Gviber,

А еще такой вопрос: Как сделать тоже самое, но имея уникальный столбец ID?
14 апр 15, 23:41    [17515731]     Ответить | Цитировать Сообщить модератору
 Re: Удаление одинаковых записей  [new]
Gviber
Member

Откуда:
Сообщений: 124
Неплохо получилось. Можно на пром =)

Схема теперь не обязательна.

--Settings
declare @TableName nvarchar(150)= 'dbo.mytable' --таблица
declare @Columns nvarchar(max) = null --Если null то все столбцы без PK. Иначе перечисление столбцов '[C1], [C2]'
declare @SaveDupl int = 1 --Если записи повторяются, то сколько из них следует сохранить

--Systems
declare @OI int=OBJECT_ID(@TableName);
IF exists(select * from sys.objects where object_id=@OI and [type]='U')
begin
	declare @SQL nvarchar(max)=
	N'with S as 
	(
		select rnk, ROW_NUMBER() OVER(partition by rnk order by rnk) pos from
		(
			SELECT RANK() OVER( order by ' +
			ISNULL(@Columns,REPLACE(
				(SELECT '['+Cl.COLUMN_NAME+']' AS 'data()'
				FROM INFORMATION_SCHEMA.COLUMNS Cl
				LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE ClKey
					ON Cl.TABLE_NAME=ClKey.TABLE_NAME 
					and Cl.TABLE_SCHEMA=ClKey.TABLE_SCHEMA
					and Cl.COLUMN_NAME=ClKey.COLUMN_NAME
				WHERE Cl.TABLE_SCHEMA=OBJECT_SCHEMA_NAME(@OI) 
					and Cl.TABLE_NAME =OBJECT_NAME(@OI) 
					and ClKey.COLUMN_NAME is null
				ORDER BY Cl.ORDINAL_POSITION
				FOR XML PATH(''))
			,' ',', '))
			+ N' ) rnk 
			FROM ['++OBJECT_SCHEMA_NAME(@OI)+N'].[' + OBJECT_NAME(@OI) +N'] 
		) T
	) 
	delete from S where pos>'+cast(ISNULL(@SaveDupl,1) as nvarchar)+' 
	and rnk = ANY
	(
		select rnk from S group by rnk having  count (*)>1
	) '
	--print @SQL
	EXEC sp_executeSQL @SQL
end 


У вас все повторы удаляются, поэтому нужно поставить @SaveDupl int = 0
15 апр 15, 11:36    [17517299]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить