删除重复的行并使用重复的行ID更新该行

时间:2018-11-30 03:25:21

标签: sql-server

这是场景:我的表中有重复的行,具有相同的ID,Name等。

1)我必须找到匹配所有条件的重复行(已完成)

2)仅在条件匹配时删除它们

3)使用已删除记录的ID并更新表中的现有行

为此,我创建了一个2临时表。 Temp1是包含所有记录的表。 Temp2由重复的行组成。

00799d60 <sub_799d60>:
  799d60:   b573        push    {r0, r1, r4, r5, r6, lr}
  799d62:   0004        movs    r4, r0
  799d64:   f000 e854   blx 799e10 <jmp_sub_100C54>
  799d68:   4b15        ldr r3, [pc, #84]   ; (799dc0 <sub_799d60+0x60>)
  799d6a:   0005        movs    r5, r0
  799d6c:   4668        mov r0, sp
  799d6e:   4798        blx r3

您可以在下面看到查​​询不应删除突出显示的最后两列,因为该部分不匹配。它应该只从Temp1和Temp2中删除匹配的条件。

enter image description here

方案2:删除Temp1中的重复记录,并使用键将Section和Classcode的数据更新为NULL。这就是我期望的突出显示为NULL的情况。 enter image description here

您可以自己运行此查询-只需复制并粘贴。

1 个答案:

答案 0 :(得分:1)

是的,对于场景1,将删除行,因为问题出在本节中。

I added this table for references. 

添加了此#temp2表以供以后使用。

 CREATE Table #Temp2 ( 
 Id int,
 Name Varchar(64),
 StudentNo INT NULL,
 ClassCode Varchar(8) NULL, 
 Section  Varchar(8) NULL, 
 )
IF OBJECT_ID('tempdb..#tmp4') IS NOT NULL
DROP TABLE #tmp4

select  t1.Id,t1.Name,t1.StudentNo,t1.Section,t1.ClassCode, 
Duplicate_RowNumber 
INTO #Duplicatedata 
from CTE as c INNER JOIN #Temp1 as t1 ON t1.Id = c.Id                                           
                            and t1.StudentNo = t1.StudentNo
                            and c.Duplicate_RowNumber >1

select * from #Duplicatedata 

这将同时满足两个条件,因为#temp 1将同时具有Elle的两行,因为您的加入条件仅针对ID和学生号。

为清楚起见,我添加了行号列。

  Id    Name    StudentNo   Section ClassCode   Duplicate_RowNumber
   1    Joe          123    I         A1                 2
   1    Joe          123    I         A1                 2
   2    Harry        113    H         X2                 2
   2    Harry        113    H         X2                 2
   3    Elle         121    E1        J1                 2
   3    Elle         121    E         J1                 2

由于您的分区基于学生编号和ID,因此每个重复的行将具有2个或更多的行号。

您可以使用此方法删除。

select 
ROW_NUMBER() over (partition by Id                                          
                            , StudentNo                                                                                 
                            order by Id, StudentNo, section)as Duplicate_RowNumber
, * into #tmp4 from #Temp1

--You can add section in your order as well for consistency purpose. 
delete   
from #tmp4  
output deleted.id, deleted.Name, deleted.StudentNo, deleted.ClassCode, 
deleted.Section into #Temp2 
where Duplicate_RowNumber > 1 

之后,您似乎想要在最终表中保留一行,而将另一行放入已删除的表中。对于Elle,由于分区不是基于section的,因此它将删除Final表中的一行并仅保留一行。

要确保从最终表中删除1行,可以使用此行。

DELETE t 
OUTPUT deleted.Id , deleted.Name ,deleted.StudentNo ,deleted.ClassCode 
,deleted.Section into @inserted  FROM    
(select *, row_number() over (Partition by tm.name, tm.studentNo Order by ID, 
StudentNo, section ) rownum  from  #temp1 tm) t
join              #Temp2 t2 on  t.Id = t2.Id 
                                         and t.Name = t2.Name
                                        and t.StudentNo = t2.StudentNo                                                      
                                        and t.ClassCode   =  t2.ClassCode 
                                        and   t.Section =  t2.Section
where t.rownum > 1 

如果您注意到我添加了此行号,那么它将不会从最终表中删除两行,因为Joe和Harry具有所有匹配的属性,并且它将删除两行。

select * from @inserted

Output you get: 

 Id Name    StudentNo   ClassCode   Section
 3  Elle    121          J1          E1
 2  Harry   113          X2          H
 1  Joe     123          A1          I

最后,您可以通过这种方式更新决赛桌。 #方案2

 update TMP 
 SET ClassCode = NULL, SECTION = NULL 
 FROM 
#Temp1 TMP 
JOIN @INSERTED I ON TMP.Id = I.Id 
                AND TMP.StudentNo = I.StudentNo 

 SELECT * FROM #Temp1 

最终输出:

 Id Name    StudentNo   ClassCode   Section
 1  Joe     123             NULL    NULL
 2  Harry   113             NULL    NULL
 3  Elle    121             NULL    NULL
 8  Jane    191             A1       E
 5  Silva   811             S1       SE
 6  Juan    411             S2       SE
 7  Carla   431             S2       SE

请注意,我已添加脚本并仅针对需要更改的部分输出,其余部分与您提供的脚本相同。