2013-08-22 75 views
216

如何刪除沒有唯一行ID的重複行?如何刪除sql server中的重複行?

我的表是

col1 col2 col3 col4 col5 col6 col7 
john 1 1 1 1 1 1 
john 1 1 1 1 1 1 
sally 2 2 2 2 2 2 
sally 2 2 2 2 2 2 

我想會留下重複取出後,在以下幾點:

我已經嘗試了一些疑問,但我認爲它們依賴於行ID因爲我沒有得到期望的結果。例如:

DELETE FROM table WHERE col1 IN (
    SELECT id FROM table GROUP BY id HAVING (COUNT(col1) > 1) 
) 
+2

這不是第一個鏈接的重複。在這個問題中沒有行ID,並且在鏈接問題中有一個行ID。非常不一樣。 –

回答

5
  1. 選擇的DISTINCT記錄到一個新表
  2. 截斷舊錶
  3. MERGE新建表回到舊錶
+14

這聽起來像一個可怕的想法,如果你有任何關係設置到表。如果表中存在標識列,那麼除非您使用IDENTITY_INSERT重新插入它們,否則這些鍵將更改。 我知道你寫了「MERGE」,但是初學者可能不知道對鍵和關係的後果,只是做一個INSERT,如果設置了任何關係會導致很大的混亂。另外,如果使用刪除規則設置了約束條件,TRUNCATE可能會刪除其他數據。 – germankiwi

+0

好男人@Declan_K – Padmanaban

+2

不好回答...怎麼樣一張有數百萬行的表......? – abzarak

484

我喜歡的CTE和ROW_NUMBER因爲這兩個組合允許我們看到哪些行被刪除(或更新),因此只需將DELETE FROM CTE...更改爲SELECT * FROM CTE

WITH CTE AS(
    SELECT [col1], [col2], [col3], [col4], [col5], [col6], [col7], 
     RN = ROW_NUMBER()OVER(PARTITION BY col1 ORDER BY col1) 
    FROM dbo.Table1 
) 
DELETE FROM CTE WHERE RN > 1 

DEMO(結果不同;我認爲這是由於錯字你的一部分)

COL1 COL2 COL3 COL4 COL5 COL6 COL7 
john 1  1  1  1  1  1 
sally 2  2  2  2  2  2 

此示例通過,因爲PARTITION BY col1的一列col1決定重複。如果要包括多列簡單地把它們添加到PARTITION BY

ROW_NUMBER()OVER(PARTITION BY Col1, Col2, ... ORDER BY OrderColumn) 
+1

謝謝你的回答。對比MSFT在這裏有一個非常複雜的答案:http://stackoverflow.com/questions/18390574/how-to-delete-duplicate-rows-in-sql-server – Barka

+0

@Tim很好的答案。如果你只想刪除john的副本,那麼怎麼辦? 'WHERE'聲明去哪了?只是好奇 – CodeEngine

+2

@ omachu23:在這種情況下並不重要,儘管我認爲它在CTE中比在外面更有效('AND COl1 ='John'')。通常你應該在CTE中使用過濾器。 –

4

微軟如何刪除重複一個合租RY整齊的指南。退房http://support.microsoft.com/kb/139444

簡單地說,這裏是刪除重複的最簡單的方法,當你只有幾行刪除:

SET rowcount 1; 
DELETE FROM t1 WHERE myprimarykey=1; 

myprimarykey是該行的標識符。

我將rowcount設置爲1,因爲我只有兩行重複。如果我有3行重複,那麼我會將rowcount設置爲2,以便刪除它看到的前兩個,並且只在表t1中留下一個。

希望它可以幫助任何人

+0

如何知道如果我有10k行有多少行重複? – Fearghal

+0

@Fearghal嘗試「選擇primaryKey,通過primaryKey從myTable組中計數(*);」 – user2070775

+0

但是如果有不同數量的重複行呢?即行a有2條記錄,行b有5條記錄,行c沒有重複記錄 – thermite

0

沒有一步到位信息丟失除去dublicated行的另一種方式是像以下:

delete from dublicated_table t1 (nolock) 
join (
    select t2.dublicated_field 
    , min(len(t2.field_kept)) as min_field_kept 
    from dublicated_table t2 (nolock) 
    group by t2.dublicated_field having COUNT(*)>1 
) t3 
on t1.dublicated_field=t3.dublicated_field 
    and len(t1.field_kept)=t3.min_field_kept 
11
DELETE from search 
where id not in (
    select min(id) from search 
    group by url 
    having count(*)=1 

    union 

    SELECT min(id) FROM search 
    group by url 
    having count(*) > 1 
) 
+0

難道你不能重寫:where id in(select max(id)... having count(*)> 1)? – Brent

+1

我不認爲有任何需要使用有或聯合,這將足夠:從搜索刪除其中id不在(從搜索組中選擇min(id)通過url) –

-1

如果你能找到重複的行數,比如你有n個重複行,則使用此命令

SET rowcount n-1 
DELETE FROM your_table 
WHERE (spacial condition) 

有關更多信息我su ggest this

2

如果你沒有引用,像外鍵,你可以這樣做。測試概念證明和測試數據重複時,我會做很多事情。

SELECT DISTINCT [COL1],[COL2],[COL3],[COL4],[COL5],[COL6],[COL7]

INTO [newtable的]

;

進入對象瀏覽器並刪除舊錶。

用舊的表名重命名新表。

60

我寧願CTE從SQL Server表中刪除重複的行

強烈建議通過保持原有

WITH CTE AS 
(
SELECT *,ROW_NUMBER() OVER (PARTITION BY col1,col2,col3 ORDER BY col1,col2,col3) AS RN 
FROM MyTable 
) 

DELETE FROM CTE WHERE RN<>1 

沒有按照本文:: http://dotnetmob.com/sql-server-article/delete-duplicate-rows-in-sql-server/

保留原創

WITH CTE AS 
(SELECT *,R=RANK() OVER (ORDER BY col1,col2,col3) 
FROM MyTable) 
  
DELETE CTE 
WHERE R IN (SELECT R FROM CTE GROUP BY R HAVING COUNT(*)>1) 
+1

窗口函數是一個很好的解決方案。 –

+0

它的工作........... 謝謝 –

2

請看下面的刪除方法。

Declare @table table 
(col1 varchar(10),col2 int,col3 int, col4 int, col5 int, col6 int, col7 int) 
Insert into @table values 
('john',1,1,1,1,1,1), 
('john',1,1,1,1,1,1), 
('sally',2,2,2,2,2,2), 
('sally',2,2,2,2,2,2) 

創建名爲@table一個示例表,並與給定的數據加載它。

enter image description here

Delete aliasName from (
Select *, 
     ROW_NUMBER() over (Partition by col1,col2,col3,col4,col5,col6,col7 order by col1) as rowNumber 
From @table) aliasName 
Where rowNumber > 1 

Select * from @table 

enter image description here

注意:如果你給在Partition by一部分的所有列,然後order by沒有太大的意義。

我知道,這個問題在三年前問過了,我的回答是Tim發佈的另一個版本,但是發佈它對任何人都有幫助。

1
with myCTE 
as 

(
select productName,ROW_NUMBER() over(PARTITION BY productName order by slno) as Duplicate from productDetails 
) 
Delete from myCTE where Duplicate>1 
1
-- this query will keep only one instance of a duplicate record. 
;WITH cte 
    AS (SELECT ROW_NUMBER() OVER (PARTITION BY col1, col2, col3-- based on what? --can be multiple columns 
             ORDER BY (SELECT 0)) RN 
     FROM Mytable) 



delete FROM cte 
WHERE RN > 1 
19

不使用CTEROW_NUMBER()你可以僅僅通過使用組通過與這裏MAX功能刪除的記錄是和例子

DELETE 
FROM MyDuplicateTable 
WHERE ID NOT IN 
(
SELECT MAX(ID) 
FROM MyDuplicateTable 
GROUP BY DuplicateColumn1, DuplicateColumn2, DuplicateColumn3) 
+3

只有在_is_一個ID /唯一字段時纔有效。 – marsze

+0

該查詢將刪除非重複記錄。 –

+1

這工作正常,謝謝。 @DerekSmalls這不會刪除我的非重複記錄。 – monteirobrena

0

With reference to https://support.microsoft.com/en-us/help/139444/how-to-remove-duplicate-rows-from-a-table-in-sql-server

去除的想法重複涉及

  • a)保護那些不重複的行
  • b)保留一起限定爲重複的許多行之一。

步驟一步

  • 1)首先鑑定那些滿足重複 定義的行和把它們插入到臨時表中,說#tableAll。
  • 2)選擇非重複(單行)或不同行到臨時表 說#tableUnique。
  • 3)刪除源表加入#table全部刪除 重複項。
  • 4)從#tableUnique中插入源表中的所有行。
  • 5)拖放#tableAll和#tableUnique