2010-08-07 75 views

回答

4
  1. 做一個查詢,讓你有資格作爲複製
  2. 進行查詢B中得到你想要保持
  3. 進行查詢的行是刪除有能力的所有行的行但不在B.

例子。

假設一個名爲table的表,其中包含一個名爲id的自動增量ID列和一個名爲name的列,您要刪除其中的雙打。在每個名稱中,您希望保留最早的記錄(ID最低的那個)。

查詢則看起來像:

SELECT * FROM table 
WHERE name IN (SELECT name FROM table GROUP BY name HAVING COUNT(*) > 1) 

查詢B.將:

SELECT * FROM table 
WHERE id IN (SELECT min(id) FROM table GROUP BY name) 

現在將這些形成刪除查詢:

DELETE FROM table 
WHERE name IN (SELECT name FROM table GROUP BY name HAVING COUNT(*) > 1) 
AND NOT id IN (SELECT min(id) FROM table GROUP BY name) 

在這個例子中,在你可以忽略第一個查詢,但是當事情變得更復雜時,這是一個很好的額外保障措施。

1

你不行。 完全重複記錄(每個字段相同的記錄)不能一個刪除,因爲在刪除查詢中,您不能在Where子句中區分它們。
唯一的辦法是做一個select distinct查詢來選擇沒有重複的所有行,然後將它們插入一個空的表中。

如果您沒有完全重複的記錄,那麼問題的解釋不正確,並且您不希望刪除重複記錄,因爲沒有任何記錄。具有不完整的相同字段的行不重複。在這種情況下,您希望刪除具有相同字段的行,在這種情況下,如果某個字段或字段集不相同,則必須指定要離開的行。

+0

我不認爲這是真的。假設你從一個表中選擇了全部,再加上一個ROW_NUMBER()列。這些行將以聚簇索引順序返回,並且您將爲每個行獲取不同的行號值。然後您可以使用它來區分WHERE子句中的重複項。 – Yellowfog 2010-08-07 19:07:30

+0

row_number是一個與order by語句一起使用的函數,只能在select查詢中使用。這只是row_number不能直接參與delete語句的原因之一。我在互聯網上找到的解決方案之一是創建一個單獨的表,將row_number作爲新字段引入,然後執行刪除語句。這不是作者想要的。 – AlexanderMP 2010-08-07 22:03:48

0

通過使用公用表表達式(CTE),您可以毫無問題地完成此任務,而無需使用任何臨時表。如果刪除是針對高流量表,請注意。刪除大量的數據可能會導致鎖定和阻塞,同時會傳輸轉錄。

注意:此代碼沒有進行任何測試,但應該可以工作(SQL 2005及更高版本)。

/* Create test data with duplicates */ 
declare @TestTable Table (Col1 int) 

insert into @TestTable 

select 1 union all 
select 1 union all 
select 2 union all 
select 3 union all 
select 3 union all 
select 4 
; 
/* Create CTE to number all duplicates (gives a running number to all identical values in Col1) */ 
with FindDupes as 
(
Select Col1,ROW_NUMBER() over (partition by Col1 order by Col1) RN 

from @TestTable 
) 
/* Delete the duplicates (anything that has a higher rownumber than one) */ 
Delete from FindDupes where RN>1 
; 

/* Select the remaining data from the table */ 
Select * from @TestTable 
-1

我覺得這個查詢將正常工作:

delete from table where id in (select count(*)c from table group by id having c > 1)