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

问题描述 投票:10回答:2

说我有这张桌子

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 | 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
)

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

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

谢谢

tsql sql-server-2008-r2
2个回答
18
投票

两种选择:

  1. 使用WITH CTEWITH CTE AS (SELECT *,RN=ROW_NUMBER() OVER(PARTITION BY data,value ORDER BY id) FROM TableName) DELETE FROM CTE WHERE RN>1 说明: 此查询将选择表的内容以及行号RN。然后使用RN> 1(这将是重复项)删除记录。 This Fiddle显示将使用此方法删除的记录。
  2. 使用NOT INDELETE FROM TableName WHERE id NOT IN (SELECT MIN(id) as id FROM TableName GROUP BY data,value) 说明: 在给定的示例中,内部查询将返回ids(1,6,4,5,7)。外部查询将从id为NOT IN(1,6,4,5,7)的表中删除记录。 This fiddle显示将使用此方法删除的记录。

建议:使用第一种方法,因为它比后者快。此外,如果id字段也重复相同的datavalue,它设法只保留一条记录。


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;
© www.soinside.com 2019 - 2024. All rights reserved.