นี่เป็นวิธีที่ดีในการกรองข้อมูลซ้ำซ้อนในตารางที่มีคอลัมน์ข้อมูลประจำตัวตามคีย์หลักที่ต้องการซึ่งคุณสามารถกำหนดได้ในขณะรันไทม์ ก่อนที่จะเริ่มฉันจะเติมข้อมูลชุดตัวอย่างเพื่อใช้งานโดยใช้รหัสต่อไปนี้:
if exists (select 1 from sys.all_objects where type='u' and name='_original')
drop table _original
declare @startyear int = 2017
declare @endyear int = 2018
declare @iterator int = 1
declare @income money = cast((SELECT round(RAND()*(5000-4990)+4990 , 2)) as money)
declare @salesrepid int = cast(floor(rand()*(9100-9000)+9000) as varchar(4))
create table
while @iterator<=50000 begin
insert
select (Select cast(floor(rand()*(@endyear-@startyear)+@startyear) as varchar(4))+'-'+ cast(floor(rand()*(13-1)+1) as varchar(2)) ), @salesrepid , @income
set @salesrepid = cast(floor(rand()*(9100-9000)+9000) as varchar(4))
set @income = cast((SELECT round(RAND()*(5000-4990)+4990 , 2)) as money)
set @iterator=@iterator+1
end
update
set monthyear=replace(monthyear, '-', '-0') where len(monthyear)=6
select * into _original from
ต่อไปฉันจะสร้างประเภทที่เรียกว่า ColumnNames:
create type ColumnNames AS table
(Columnnames varchar(max))
ในที่สุดฉันจะสร้าง proc ที่จัดเก็บโดยมี 3 ข้อควรระวังต่อไปนี้: 1. proc จะใช้พารามิเตอร์ที่จำเป็น @tablename ซึ่งกำหนดชื่อของตารางที่คุณกำลังลบออกจากฐานข้อมูลของคุณ 2. proc มีพารามิเตอร์ที่เป็นทางเลือก @columns ซึ่งคุณสามารถใช้เพื่อกำหนดฟิลด์ที่ประกอบเป็นคีย์หลักที่ต้องการซึ่งคุณกำลังลบ หากช่องนี้เว้นว่างไว้จะถือว่าฟิลด์ทั้งหมดที่อยู่นอกเหนือจากคอลัมน์ identity ประกอบเป็นคีย์หลักที่ต้องการ 3. เมื่อลบระเบียนที่ซ้ำกันระเบียนที่มีค่าต่ำสุดในคอลัมน์ข้อมูลประจำตัวจะยังคงอยู่
นี่คือ delete_dupes ที่จัดเก็บ proc ของฉัน:
create proc delete_dupes (@tablename varchar(max), @columns columnnames readonly)
as
begin
declare @table table (iterator int, name varchar(max), is_identity int)
declare @tablepartition table (idx int identity, type varchar(max), value varchar(max))
declare @partitionby varchar(max)
declare @iterator int= 1
if exists (select 1 from @columns) begin
declare @columns1 table (iterator int, columnnames varchar(max))
insert @columns1
select 1, columnnames from @columns
set @partitionby = (select distinct
substring((Select ', '+t1.columnnames
From @columns1 t1
Where T1.iterator = T2.iterator
ORDER BY T1.iterator
For XML PATH ('')),2, 1000) partition
From @columns1 T2 )
end
insert @table
select 1, a.name, is_identity from sys.all_columns a join sys.all_objects b on a.object_id=b.object_id
where b.name = @tablename
declare @identity varchar(max)= (select name from @table where is_identity=1)
while @iterator>=0 begin
insert @tablepartition
Select distinct case when @iterator=1 then 'order by' else 'over (partition by' end ,
substring((Select ', '+t1.name
From @table t1
Where T1.iterator = T2.iterator and is_identity=@iterator
ORDER BY T1.iterator
For XML PATH ('')),2, 5000) partition
From @table T2
set @iterator=@iterator-1
end
declare @originalpartition varchar(max)
if @partitionby is null begin
select @originalpartition = replace(b.value+','+a.type+a.value ,'over (partition by','') from @tablepartition a cross join @tablepartition b where a.idx=2 and b.idx=1
select @partitionby = a.type+a.value+' '+b.type+a.value+','+b.value+') rownum' from @tablepartition a cross join @tablepartition b where a.idx=2 and b.idx=1
end
else
begin
select @originalpartition=b.value +','+ @partitionby from @tablepartition a cross join @tablepartition b where a.idx=2 and b.idx=1
set @partitionby = (select 'OVER (partition by'+ @partitionby + ' ORDER BY'+ @partitionby + ','+b.value +') rownum'
from @tablepartition a cross join @tablepartition b where a.idx=2 and b.idx=1)
end
exec('select row_number() ' + @partitionby +', '+@originalpartition+' into ##temp from '+ @tablename+'')
exec(
'delete a from _original a
left join ##temp b on a.'+@identity+'=b.'+@identity+' and rownum=1
where b.rownum is null')
drop table
end
เมื่อเป็นไปตามนี้คุณสามารถลบระเบียนที่ซ้ำกันทั้งหมดของคุณได้โดยเรียกใช้ proc หากต้องการลบสิ่งที่ทับซ้อนโดยไม่กำหนดคีย์หลักที่ต้องการให้ใช้การเรียกนี้:
exec delete_dupes '_original'
หากต้องการลบสิ่งที่ทับซ้อนตามคีย์หลักที่ต้องการกำหนดให้ใช้การเรียกนี้:
declare @table1 as columnnames
insert @table1
values ('salesrepid'),('sale')
exec delete_dupes '_original' , @table1