关于sql server:T-SQL:删除所有重复的行,但保留一个

T-SQL: Deleting all duplicate rows but keeping one

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
SQL - How can I remove duplicate rows?

我有一个行数非常多的表。 不允许重复,但由于行如何创建的问题我知道这个表中有一些重复。
我需要从关键列的角度消除额外的行。 其他一些列的数据可能略有不同,但我并不关心。 我仍然需要保留其中一行。 SELECT DISTINCT将无法工作,因为它在所有列上运行,我需要根据键列抑制重复。

如何删除额外的行但仍保持有效?


您没有说明您使用的是哪个版本,但在SQL 2005及更高版本中,您可以使用带有OVER子句的公用表表达式。它有点像这样:

1
2
3
4
5
6
WITH cte AS (
  SELECT[foo], [bar],
     ROW_NUMBER() OVER(PARTITION BY foo, bar ORDER BY baz) AS [rn]
  FROM TABLE
)
DELETE cte WHERE [rn] > 1

玩弄它,看看你得到了什么。

(编辑:为了有所帮助,有人编辑了CTE中的ORDER BY子句。要清楚,你可以按照你想要的任何顺序排序,它不一定是cte返回的列之一。事实上。 ,这里常见的用例是"foo,bar"是组标识符,"baz"是某种时间戳。??为了保持最新,你要做ORDER BY baz desc)


示例查询:

1
2
3
4
5
6
7
DELETE FROM TABLE
WHERE ID NOT IN
(
SELECT MIN(ID)
FROM TABLE
GROUP BY Field1, Field2, Field3, ...
)

此处fields是要在其上对重复行进行分组的列。


这是我对它的一种扭曲,有一个可运行的例子。请注意,这仅适用于Id唯一且您在其他列中具有重复值的情况。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
DECLARE @SampleData AS TABLE (Id INT, Duplicate VARCHAR(20))

INSERT INTO @SampleData
SELECT 1, 'ABC' UNION ALL
SELECT 2, 'ABC' UNION ALL
SELECT 3, 'LMN' UNION ALL
SELECT 4, 'XYZ' UNION ALL
SELECT 5, 'XYZ'

DELETE FROM @SampleData WHERE Id IN (
    SELECT Id FROM (
        SELECT
            Id
            ,ROW_NUMBER() OVER (PARTITION BY [Duplicate] ORDER BY Id) AS [ItemNumber]
            -- Change the partition columns to include the ones that make the row distinct
        FROM
            @SampleData
    ) a WHERE ItemNumber > 1 -- Keep only the first unique item
)

SELECT * FROM @SampleData

结果如下:

1
2
3
4
5
Id          Duplicate
----------- ---------
1           ABC
3           LMN
4           XYZ

不知道为什么这就是我首先想到的......绝对不是最简单的方法,但它有效。