试图删除SQL数据库中的重复条目删除了所有记录。什么地方出了错?

时间:2009-08-26 19:24:18

标签: sql sql-server sql-server-2005

我尝试删除数据库中的重复记录。唯一的区别是PrimaryKey是一个uniqueidentifier。我有大约1500个被欺骗的条目,所以我正在查看大约3000个条目。所以我分开了大约60个条目(根据收到的日期)并执行了我的代码,将它们减少到30,而OH CRAP 30则消失了!这是我试过的代码:

DELETE dupes
FROM [emailTable] dupes, [emailTable] fullTable
WHERE (dupes.ReceivedOn > '2009-08-18 23:59:59.999' AND dupes.ReceivedOn < '2009-08-20 00:00:00.000')
      AND (dupes.emlPath = fullTable.emlPath)
      AND NOT (dupes.GUID = fullTable.GUID)

我的目标是删除副本。我不关心哪一个......但是我需要两个条目中的一个留在服务器上...任何人都可以解释我做错了什么?

6 个答案:

答案 0 :(得分:7)

您可以在没有第二张表的情况下执行此操作。像这样:

SELECT * FROM emailTable
WHERE EXISTS (
    SELECT * FROM emailTable AS t2
    WHERE t2.emlPath = emailTable.emlPath AND
    t2.GUID > emailTable.GUID)

这将显示哪些记录即将被删除。如果没关系,请将其更改为:

DELETE FROM emailTable
WHERE EXISTS (
    SELECT * FROM emailTable AS t2
    WHERE t2.emlPath = emailTable.emlPath AND
    t2.GUID > emailTable.GUID)

t2.GUID > emailTable.GUID将确保包含该emlPath的一条记录保留在表格中。

答案 1 :(得分:2)

您应该使用子选择进行删除,而不是连接。

以这种方式执行此操作的好处是,您可以在实际删除之前预览要删除的GUID。 (只需自己运行select查询)

这个outta这样做,它将删除最小的GUID

    delete from emailTable where GUID in
    (

     select MIN(dupe.GIUD) from emailTable dupe
       INNER JOIN emailTable noDupe 
         ON dupe.emlPath=noDupe.emlPath 
            where recievedOn between '2009-8-18' and '2009-8-20'
               GROUP BY dupe.emlPath
    )

答案 2 :(得分:1)

您做错了是您的查询不排除任何重复项。它挑选出与具有相同路径的另一个副本不同的重复项,但每个重复项与另一个重复项不同。

您要做的是首先挑选出您想要保留的副本,例如:

select min(GUID)
from emailTable
where ReceivedOn > '...' and ReceivedOn < '...'
group by emlPath
having count(*) > 1

然后删除除那些之外的所有重复项。

答案 3 :(得分:0)

您不应在加入中使用“=”。即“AND NOT(dupes.GUID = fullTable.GUID)”由于重复行的GUID必须不同,此条件不会执行任何操作。

你应该使用大于。即

delete from emailTable 
WHERE EXISTS
(
    SELECT ID FROM emailTable t2
    WHERE emailTable.GUID > t2.GUID
    AND emailTable.emlPath= t2.emlPath
)

答案 4 :(得分:0)

我更喜欢使用公用表表达式和ROW_NUMBER():

with cte as (
   select row_number() over (partition by emlPath order by GUID) as eml_no
      , ReceivedOn
   from [emailTables])
delete from cte
   where eml_no > 1
   and ReceivedOn between '2009-08-18 23:59:59.999' AND '2009-08-20 00:00:00.000';

我喜欢这个,因为它可以控制删除哪个重复行。我可以删除第三个并保留两个,我可以选择我想要保留第一个的任何订单号,它可以很好地处理关系。

答案 5 :(得分:0)

由于所有帖子的帮助,这是我最终得到的代码:

DELETE A
  FROM [emailTable] A, [emailTable] B
  WHERE A.MessageID = B.MessageID
        AND A.GUID > B.GUID