Microsoft SQL Server
Transact-SQL

Удаление дубликатов записей

Опубликовано: 29 мар 06
Рейтинг:

Автор: Роман Дынник
Прислал:

create table #t(
  f1 varchar(10)
 ,f2 varchar(10)
 ,f3 varchar(10)
)
 
declare @f1 varchar(10)
declare @f2 varchar(10)
declare @f3 varchar(10)
declare @c int
declare @sql nvarchar(4000)

--3 дубликата
insert into #t values('1','2','3')
insert into #t values('1','2','3')
insert into #t values('1','2','3')
--2 дубликата
insert into #t values('4','5','6')
insert into #t values('4','5','6')
--0 дубликатов
insert into #t values('2','5','3')
--

--перед удалением
select * from #t
--курсор-выборка дубликатов
declare cur cursor 
	for 
		select count(*) as c, f1, f2, f3
			from #t
			group by f1, f2, f3
			having count(*)>1

open cur
--цикл по курсору и выполнение удаления дубликатов
while 1=1
	begin
		fetch next from cur into @c, @f1, @f2, @f3
		if @@fetch_status<>0 break
		set @sql = N' SET ROWCOUNT '+CONVERT(varchar(255),@c-1)+';'
				 + N' delete from #t where'
				 + N'	  f1='+@f1
				 + N' AND f2='+@f2
				 + N' AND f3='+@f3
				 + N' ;'
		print @sql
		exec sp_executesql @sql
	end
close cur
deallocate cur

--после удаления
select * from #t
--
drop table #t

Комментарии


  • --Если предположить, что в табличке всё таки есть уникальный идентификатор (обычно он таки есть), перепишем DELETE одним запросом без CTE
    declare @t table( id int identity(1,1), col varchar(50) );

    insert into @t( col )
    values( 'sdfdfs' ),
    ( 'kshrfuew' ),
    ( 'kjgadfsydasd' ),
    ( 'kshrfuew' ),
    ( 'kjgadfsydasd' ),
    ( 'kjgadfsydasd' )

    select * from @t

    delete t
    from @t t
    where t.id in (
    select id
    from (
    select id, row_number() over ( partition by col order by col ) as rn
    from @t
    ) t2
    where t2.id = t.id and t2.rn > 1
    )

    select * from @t

  • Ещё один неплохой способ:

    USE tempdb

    IF EXISTS(SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'#Test1'))
    BEGIN
    DROP TABLE #Test1
    END

    CREATE TABLE #Test1(
    Name NVARCHAR(20),
    LastName NVARCHAR(40),
    Birth DATETIME)

    INSERT INTO #Test1
    SELECT 'Вася', 'Петров', CONVERT(DATETIME, '2000-01-01 00:00:00.000')
    UNION ALL
    SELECT 'Петя', 'Васильев', CONVERT(DATETIME, '2000-02-02 00:00:00.000')
    UNION ALL
    SELECT 'Коля', 'Сидоров', CONVERT(DATETIME, '2000-04-04 00:00:00.000')
    UNION ALL
    SELECT 'Петя', 'Васильев', CONVERT(DATETIME, '2000-02-02 00:00:00.000');

    WITH Q(RN) AS
    (SELECT ROW_NUMBER() OVER (PARTITION BY Name, LastName, Birth ORDER BY Name, LastName, Birth) AS RN FROM #Test1)
    DELETE Q WHERE RN > 1

    SELECT * FROM #Test1

    DROP TABLE #Test1



Необходимо войти на сайт, чтобы оставлять комментарии

Раздел FAQ: Microsoft SQL Server / Transact-SQL / Удаление дубликатов записей