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

时间:2014-05-06 13:13:05

标签: tsql 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

我希望删除每个数据具有重复值的行,同时保留具有最小ID的行,例如结果将是

id | data | value
-----------------
 1 |   a  |   A
 4 |   a  |   B
 5 |   b  |   C
 6 |   c  |   A
 7 |   c  |   C

我知道一种方法是做一个像:

这样的联盟
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
)

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

我更希望用更少的代码来回答更复杂的代码。有没有更简洁的方法来编码?

谢谢

2 个答案:

答案 0 :(得分:18)

两种选择:

  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
    

    <强>解释

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

    This Fiddle显示将使用此方法删除的记录。

  2. 使用NOT IN

    DELETE FROM TableName
    WHERE id NOT IN
          (SELECT MIN(id) as id
           FROM TableName
           GROUP BY data,value)
    

    说明:

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

    This fiddle显示将使用此方法删除的记录。

  3. 建议:使用第一种方法,因为它比后者快。此外,如果同一iddata的{​​{1}}字段也重复,则只会保留一条记录。

答案 1 :(得分:0)

我想为此查询添加MYSQL解决方案

建议1:8.0版之前的MySQL不支持WITH子句

建议2:抛出此错误(您不能在FROM子句中指定表TableName进行更新

因此解决方案将

DELETE FROM TableName WHERE id NOT IN
  (SELECT MIN(id) as id
   FROM (select * from TableName) as t1
   GROUP BY data,value) as t2;