2009-06-12 138 views
44

我有如下表下面的記錄在它刪除從SQL表中重複記錄沒有主鍵

create table employee 
(
EmpId number, 
EmpName varchar2(10), 
EmpSSN varchar2(11) 
); 

insert into employee values(1, 'Jack', '555-55-5555'); 
insert into employee values (2, 'Joe', '555-56-5555'); 
insert into employee values (3, 'Fred', '555-57-5555'); 
insert into employee values (4, 'Mike', '555-58-5555'); 
insert into employee values (5, 'Cathy', '555-59-5555'); 
insert into employee values (6, 'Lisa', '555-70-5555'); 
insert into employee values (1, 'Jack', '555-55-5555'); 
insert into employee values (4, 'Mike', '555-58-5555'); 
insert into employee values (5, 'Cathy', '555-59-5555'); 
insert into employee values (6 ,'Lisa', '555-70-5555'); 
insert into employee values (5, 'Cathy', '555-59-5555'); 
insert into employee values (6, 'Lisa', '555-70-5555'); 

我沒有在這個表中的任何主鍵。但我在上面記載我表已經。 我想刪除在EmpId和EmpSSN字段中具有相同值的重複記錄。

例如:的Emp ID 5

任何一個可以幫助我來構建查詢,刪除那些重複的記錄提前

感謝

+0

你可以*添加*主鍵? 你正在使用什麼數據庫系統?甲骨文?請在您的問題中指定! – 2009-06-12 07:19:47

+2

如果它具有相同的EmpID和EmpSSn,但名稱不同,該怎麼辦? – cjk 2009-06-12 07:24:29

+0

它的SQL服務器2005 – Shyju 2009-06-12 08:02:58

回答

51

添加主鍵(下面的代碼)

運行正確刪除(下面的代碼)

考慮爲什麼你woudln't要保持該主鍵。


假設MSSQL或兼容:

ALTER TABLE Employee ADD EmployeeID int identity(1,1) PRIMARY KEY; 

WHILE EXISTS (SELECT COUNT(*) FROM Employee GROUP BY EmpID, EmpSSN HAVING COUNT(*) > 1) 
BEGIN 
    DELETE FROM Employee WHERE EmployeeID IN 
    (
     SELECT MIN(EmployeeID) as [DeleteID] 
     FROM Employee 
     GROUP BY EmpID, EmpSSN 
     HAVING COUNT(*) > 1 
    ) 
END 
6

您可以創建一個包含的select distinct臨時表#tempemployeeemployee表。 然後delete from employee。 然後insert into employee select from #tempemployee

像Josh說的 - 即使你知道重複,刪除它們將是無法實現的,因爲如果它與另一個記錄完全相同,則實際上不能引用特定記錄。

+2

這裏只有一招:如果名稱不同但ID/SSN匹配。你必須以某種方式選擇一個,因爲區別對此沒有幫助。 – Josh 2009-06-12 07:19:39

+1

+1這是最直接,最便攜的解決方案。 OP沒有說明他使用什麼品牌的數據庫。 – 2009-06-12 07:22:21

+0

@Josh:從OP的樣本看來,這看起來不是問題。所有列中的重複行都是相同的。 – 2009-06-12 07:23:21

0

我不是SQL專家,所以請忍受我。我相信你很快就會得到更好的答案。以下是如何找到重複記錄。

select t1.empid, t1.empssn, count(*) 
from employee as t1 
inner join employee as t2 on (t1.empid=t2.empid and t1.empssn = t2.empssn) 
group by t1.empid, t1.empssn 
having count(*) > 1 

刪除它們會更棘手,因爲在刪除語句中可以使用任何數據來區分重複項。我懷疑答案會涉及row_number()或添加一個標識列。

22

使用行號重複的記錄進行區分。保持第一行編號爲的EmpID/EmpSSN並刪除其餘:

DELETE FROM Employee a 
    WHERE ROW_NUMBER() <> (SELECT MIN(ROW_NUMBER()) 
           FROM Employee b 
           WHERE a.EmpID = b.EmpID 
           AND a.EmpSSN = b.EmpSSN) 
-1
select t1.* from employee t1, employee t2 where t1.empid=t2.empid and t1.empname = t2.empname and t1.salary = t2.salary 
group by t1.empid, t1.empname,t1.salary having count(*) > 1 
2

如果您不希望創建您可以在SQL Server中使用top命令一個新的主鍵:

declare @ID int 
while EXISTS(select count(*) from Employee group by EmpId having count(*)> 1) 
begin 
    select top 1 @ID = EmpId 
    from Employee 
    group by EmpId 
    having count(*) > 1 

    DELETE TOP(1) FROM Employee WHERE EmpId = @ID 
end 
0
create unique clustered index Employee_idx 
on Employee (EmpId,EmpSSN) 
with ignore_dup_key

如果您不需要它,您可以刪除索引。

-3
ALTER IGNORE TABLE test 
      ADD UNIQUE INDEX 'test' ('b'); 

@這裏的 'B' 是列名的唯一性, @這裏 '測試' 是索引名。

-2
DELETE FROM 'test' 
USING 'test' , 'test' as vtable 
WHERE test.id>vtable.id and test.common_column=vtable.common_column 

利用這一點,我們可以刪除重複記錄

69

這是非常簡單的。我在SQL Server 2008嘗試

DELETE SUB FROM 
(SELECT ROW_NUMBER() OVER (PARTITION BY EmpId, EmpName, EmpSSN ORDER BY EmpId) cnt 
FROM Employee) SUB 
WHERE SUB.cnt > 1 
9
With duplicates 

As 
(Select *, ROW_NUMBER() Over (PARTITION by EmpID,EmpSSN Order by EmpID,EmpSSN) as Duplicate From Employee) 

delete From duplicates 

Where Duplicate > 1 ; 

這將更新表,並從表中刪除所有重複!

6
select distinct * into newtablename from oldtablename 

現在,newtablename將沒有重複的記錄。

只需在sql server的對象資源管理器中按F2鍵即可更改表名(newtablename)。

0

沒有ID,沒有rowcount()或沒有temp table需要....

WHILE 
    (
    SELECT COUNT(*) 
    FROM TBLEMP 
    WHERE EMPNO 
      IN (SELECT empno from tblemp group by empno having count(empno)>1)) > 1 


DELETE top(1) 
FROM TBLEMP 
WHERE EMPNO IN (SELECT empno from tblemp group by empno having count(empno)>1) 
0

中有一個表ID和名稱,這裏的名字用不同的ID重複所以你可以使用這個查詢兩列: 。 。

DELETE FROM dbo.tbl1 
WHERE id NOT IN (
    Select MIN(Id) AS namecount FROM tbl1 
    GROUP BY Name 
) 
0

有沒有主鍵的數據庫表真的和會說非常不好的做法......所以加一個(ALTER TABLE)

運行後,你,直到你看不到任何更多的重複記錄(即是具有COUNT的目的)

DELETE FROM [TABLE_NAME] WHERE [Id] IN 
(
    SELECT MAX([Id]) 
    FROM [TABLE_NAME] 
    GROUP BY [TARGET_COLUMN] 
    HAVING COUNT(*) > 1 
) 


SELECT MAX([Id]),[TABLE_NAME], COUNT(*) AS dupeCount 
FROM [TABLE_NAME] 
GROUP BY [TABLE_NAME] 
HAVING COUNT(*) > 1 

MAX([ID])將導致情況下刪除最新記錄(首次創建後添加的),你希望相反的意思是,在需要刪除第一條記錄的情況下,並插入最後一條記錄,請使用MIN([Id])

1

ITS容易使用下面查詢

WITH Dups AS 
(
    SELECT col1,col2,col3, 
ROW_NUMBER() OVER(PARTITION BY col1,col2,col3 ORDER BY (SELECT 0)) AS rn 
FROM mytable 
) 
DELETE FROM Dups WHERE rn > 1 
3

代碼

DELETE DUP 
FROM 
( 
    SELECT ROW_NUMBER() OVER (PARTITION BY Clientid ORDER BY Clientid) AS Val 
    FROM ClientMaster 
) DUP 
WHERE DUP.Val > 1 

說明

使用一個內部查詢構造的圖上,其中包括基於一個字段的表Row_Number(),按您希望唯一的那些列進行分區。

從這個內部查詢的結果中刪除,選擇沒有行號爲1的任何東西;即重複;不是原來的。

對於有效的語法,row_number窗口函數的order by子句是必需的;你可以在這裏輸入任何列名稱。如果您希望更改哪些結果被視爲重複(例如保留最早或最近等),那麼這裏使用的列確實很重要;即您想要指定順序,以便您希望保留的記錄在結果中排​​在第一位。