SQL用于删除具有重复值的行,同时保留一个

use*_*188 13 t-sql sql-server-2008-r2

说我有这张桌子

id | data | value
-----------------
 1 |   a  |   A
 2 |   a  |   A
 3 |   a  |   A
 4 |   a  |   B
 5 |   b  |   C
 6 |   c  |   A
 7 |   c  |   C
 8 |   c  |   C
Run Code Online (Sandbox Code Playgroud)

我想删除那些具有重复值的行,同时保持每个数据的最小值,例如结果将是

id | data | value
-----------------
 1 |   a  |   A
 4 |   a  |   B
 5 |   b  |   C
 6 |   c  |   A
 7 |   c  |   C
Run Code Online (Sandbox Code Playgroud)

我知道一种方法是做一个像这样的联盟:

SELECT 1 [id], 'a' [data], 'A' [value] INTO #test UNION SELECT 2, 'a', 'A'
UNION SELECT 3, 'a', 'A' UNION SELECT 4, 'a', 'B'
UNION SELECT 5, 'b', 'C' UNION SELECT 6, 'c', 'A'
UNION SELECT 7, 'c', 'C' UNION SELECT 8, 'c', 'C'

SELECT * FROM #test WHERE id NOT IN (
    SELECT MIN(id) FROM #test
    GROUP BY [data], [value]
    HAVING COUNT(1) > 1
    UNION
    SELECT MIN(id) FROM #test
    GROUP BY [data], [value]
    HAVING COUNT(1) <= 1
)
Run Code Online (Sandbox Code Playgroud)

但是这个解决方案必须重复两次相同的组(考虑真实情况是一个庞大的组,大于20列)

我希望用更少的代码更简单的答案,而不是复杂的代码.有没有更简洁的方法来编码这个?

谢谢

Rag*_*ull 19

两种选择:

  1. 使用WITH CTE:

    WITH CTE AS 
    (SELECT *,RN=ROW_NUMBER() OVER(PARTITION BY data,value ORDER BY id) 
     FROM TableName)
    DELETE FROM CTE WHERE RN>1
    
    Run Code Online (Sandbox Code Playgroud)

    说明:

    此查询将选择表的内容以及行号RN.然后删除RN> 1 的记录(这将是重复的).

    此小提琴显示将使用此方法删除的记录.

  2. 使用NOT IN:

    DELETE FROM TableName
    WHERE id NOT IN
          (SELECT MIN(id) as id
           FROM TableName
           GROUP BY data,value)
    
    Run Code Online (Sandbox Code Playgroud)

    说明:

    在给定的示例中,内部查询将返回ids(1,6,4,5,7).外部查询将从id为NOT IN(1,6,4,5,7)的表中删除记录.

    这个小提琴显示了使用此方法删除的记录.

建议:使用第一种方法,因为它比另一种方法更快.