【问题标题】:SQL Server 2008: delete duplicate rowsSQL Server 2008:删除重复行
【发布时间】:2016-07-08 19:17:50
【问题描述】:

我的表中有重复的行,如何根据单个列的值删除它们?

例如

uniqueid, col2, col3 ...
1, john, simpson
2, sally, roberts
1, johnny, simpson

delete any duplicate uniqueIds
to get 

1, John, Simpson
2, Sally, Roberts

【问题讨论】:

  • 你会保留哪个?约翰尼还是约翰?
  • 我不介意我保留哪个。

标签: sql sql-server-2008 duplicates


【解决方案1】:

您可以在 cte 中DELETE

WITH cte AS (SELECT *,ROW_NUMBER() OVER(PARTITION BY uniqueid ORDER BY col2)'RowRank'
             FROM Table)
DELETE FROM cte 
WHERE RowRank > 1

ROW_NUMBER() 函数为每一行分配一个数字。 PARTITION BY 用于为该组中的每个项目开始编号,在这种情况下,uniqueid 的每个值将从 1 开始编号并从那里向上。 ORDER BY 确定数字的顺序。由于每个 uniqueid 从 1 开始编号,因此 ROW_NUMBER() 大于 1 的任何记录都有重复的 uniqueid

要了解ROW_NUMBER() 函数的工作原理,请尝试一下:

SELECT *,ROW_NUMBER() OVER(PARTITION BY uniqueid ORDER BY col2)'RowRank'
FROM Table
ORDER BY uniqueid

您可以调整ROW_NUMBER() 函数的逻辑来调整您将保留或删除的记录。

例如,也许您想分多个步骤执行此操作,首先删除具有相同姓氏但不同名字的记录,您可以将姓氏添加到PARTITION BY

WITH cte AS (SELECT *,ROW_NUMBER() OVER(PARTITION BY uniqueid, col3 ORDER BY col2)'RowRank'
             FROM Table)
DELETE FROM cte 
WHERE RowRank > 1

【讨论】:

  • 这是最干净的方法。
  • 你能解释一下 'SELECT *,ROW_NUMBER() OVER(PARTITION BY ID, ORDER BY col2)'RowRank'FROM Table' 的作用吗?
  • 当然,更新了答案以包含ROW_NUMBER()的描述
  • Id 是指 UniqueId - PARTITION BY ID。还有为什么 Orderby Col2 - 我不在乎 col2 是否重复,我想删除 UniqueId 的重复而不关心留下的重复项
  • 是的,在您的情况下,ID = UniqueId。 ORDER BY 也可以是 ORDER BY (SELECT 1) 以使其任意。同样,PARTITION BY 定义了将从 1 到 n 编号的字段,ORDER BYROW_NUMBER() 函数中是必需的,因此它实际上决定了删除哪些重复项,哪些不删除。
【解决方案2】:

您可能有一个 由数据库在插入时分配的行 ID,并且实际上是唯一的。在我的示例中,我将调用此 rowId。

rowId |uniqueid |col2  |col3
----- |-------- |----  |----
1      10        john   simpson
2      20        sally  roberts
3      10        johnny simpson

您可以通过对应该是唯一的事物(无论是一列还是多列)进行分组来删除重复项,然后从每个组中获取一个 rowId,并删除除这些 rowId 之外的所有其他内容。在内部查询中,表中的所有内容都会有一个 rowId,除了重复的行。

select * 
--DELETE 
FROM MyTable 
WHERE rowId NOT IN 
(SELECT MIN(rowId) 
 FROM MyTable 
 GROUP BY uniqueid);

您也可以使用 MAX 代替 MIN 以获得类似的结果。

【讨论】:

    【解决方案3】:
    DECLARE @du TABLE (
        id INT,  
        Name VARCHAR(4)
    )
    
    INSERT INTO @du VALUES(1,'john')
    INSERT INTO @du VALUES(2,'jane')
    INSERT INTO @du VALUES(1,'john')
    
    ;WITH dup (id,dp)
    AS
    (SELECT id
    , ROW_NUMBER() OVER(PARTITION BY id ORDER BY Name) AS dp
    FROM @du)
    DELETE FROM dup
    WHERE dp > 1
    
    SELECT *
    FROM @du
    

    【讨论】:

      【解决方案4】:

      这是删除重复项的简单魔法

      select * into NewTable from ExistingTable
      union
      select * from ExistingTable;
      

      【讨论】:

        【解决方案5】:

        DELETE FROM table WHERE uniqueid='1' AND col2='john' 或者您将col2='john' 更改为col2='johnny'。取决于您要删除的记录。

        您最初是如何得到两个相同的“唯一”ID 的?

        【讨论】:

        • 这仅回答了 OP 给出的非常具体的示例,因为这只是他们可能希望提供更通用解决方案的示例
        • 这个例子是硬编码的,不是吗?我仍在试图弄清楚我是如何被骗子告终的。
        【解决方案6】:

        您有很多方法可以删除重复记录,其中一些如下............

        删除重复记录的不同方法

        使用 Row_Number() 函数和 CTE

          with CTE(DuplicateCount) as  ( SELECT  ROW_NUMBER() OVER
        (PARTITION by UniqueId order by UniqueId ) as DuplicateCount from
        Table1 ) Delete from CTE where DuplicateCount > 1
        
          .Without using CTE*
        
        Delete DuplicateCount from ( Select Row_Number() over(Partition by
        UniqueId order by UniqueId) as Dup from Table1 ) DuplicateCount 
        where DuplicateCount.Dup > 1
        
         .Without using row_Number() and CTE
        
        Delete from Subject where RowId not in(select Min(RowId ) from
        Subject group by UniqueId)
        

        【讨论】:

          猜你喜欢
          • 2015-03-21
          • 2019-12-04
          • 2017-11-16
          • 1970-01-01
          • 1970-01-01
          • 2023-02-06
          • 1970-01-01
          • 2015-12-09
          • 1970-01-01
          相关资源
          最近更新 更多