2012-10-04 65 views
3

可能重複:
How can I remove duplicate rows?
Remove duplicates using only a MySQL query?MySQL中,如何合併表項的重複

我有一個大桌子〜14M的條目。表類型是MyISAM而不是InnoDB。

不幸的是,我在這個表中,我發現有以下要求一些重複的條目:

SELECT device_serial, temp, tstamp, COUNT(*) c FROM up_logs GROUP BY device_serial, temp, tstamp HAVING c > 1 

爲了避免將來這些重複,我想我目前的指數轉換爲唯一約束使用SQL要求:

ALTER TABLE up_logs DROP INDEX UK_UP_LOGS_TSTAMP_DEVICE_SERIAL, 
ALTER TABLE up_logs ADD INDEX UK_UP_LOGS_TSTAMP_DEVICE_SERIAL ( `tstamp` , `device_serial`) 

但在此之前,我需要清理我的副本!

我的問題是:我怎樣才能保留我的重複條目只有一個條目?請記住,我的表包含14M條目,所以如果可能的話,我希望避免循環。

歡迎任何評論!

+0

可能接受的答案在這個問題上也將對你有所幫助:http://stackoverflow.com/questions/18932/how-can-i-remove-duplicate-rows – MBozic

+0

你有任何ID或什麼獨特的?你可以展示桌子的結構嗎? – jcho360

回答

4

在需要作爲唯一身份的列上創建新的唯一鍵會自動清除所有重複項的表。

ALTER IGNORE TABLE `table_name` 
    ADD UNIQUE KEY `key_name`(`column_1`,`column_2`); 

忽略部分不允許出現第一個錯誤後腳本終止。默認行爲是刪除重複項。

+0

謝謝你,你的解決方案是完美的,非常高效 – sdespont

1

這就是你如何刪除重複的行...我會寫你我的例子,你需要適用於你的代碼。我有ID演員表,我想刪除行重複first_name

mysql> select actor_id, first_name from actor_2; 
+----------+-------------+ 
| actor_id | first_name | 
+----------+-------------+ 
|  1 | PENELOPE | 
|  2 | NICK  | 
|  3 | ED   | 
.... 
|  199 | JULIA  | 
|  200 | THORA  | 
+----------+-------------+ 

200 rows in set (0.00 sec) 

- 現在我使用了一個名爲@a變量獲得ID下一行是否具有相同的FIRST_NAME(重複,無效,如果它是不)。

mysql> select if([email protected],actor_id,null) as first_names,@a:=first_name from actor_2 order by first_name; 
+---------------+----------------+ 
| first_names | @a:=first_name | 
+---------------+----------------+ 
|   NULL | ADAM   | 
|   71 | ADAM   | 
|   NULL | AL    | 
|   NULL | ALAN   | 
|   NULL | ALBERT   | 
|   125 | ALBERT   | 
|   NULL | ALEC   | 
|   NULL | ANGELA   | 
|   144 | ANGELA   | 
... 
|   NULL | WILL   | 
|   NULL | WILLIAM  | 
|   NULL | WOODY   | 
|   28 | WOODY   | 
|   NULL | ZERO   | 
+---------------+----------------+ 
200 rows in set (0.00 sec) 

- 現在我們只能得到複製ID:

mysql> select first_names from (select if([email protected],actor_id,null) as first_names,@a:=first_name from actor_2 order by first_name) as t1; 
    +-------------+ 
    | first_names | 
    +-------------+ 
    |  NULL | 
    |   71 | 
    |  NULL | 
    ... 
    |   28 | 
    |  NULL | 
    +-------------+ 
    200 rows in set (0.00 sec) 

-the最後一步,讓我們刪除!

mysql> delete from actor_2 where actor_id in (select first_names from (select if([email protected],actor_id,null) as first_names,@a:=first_name from actor_2 order by first_name) as t1); 
Query OK, 72 rows affected (0.01 sec) 

- 現在讓我們檢查表:

mysql> select count(*) from actor_2 group by first_name; 
+----------+ 
| count(*) | 
+----------+ 
|  1 | 
|  1 | 
|  1 | 
... 
|  1 | 
+----------+ 
128 rows in set (0.00 sec) 

它的工作原理,如果你有任何問題,我寫回

4

因爲MySQL允許在子查詢更新/刪除語句,但如果他們參考你想更新的表格,我先創建一個原始表格的副本。然後:

DELETE FROM original_table 
WHERE id NOT IN( 
    SELECT id FROM copy_table 
    GROUP BY column1, column2, ... 
); 

但我可以想像,複製表14M條目需要一些時間......選擇項目時保留複製可能使其更快:

INSERT INTO copy_table 
    SELECT * FROM original_table 
    GROUP BY column1, column2, ...; 

然後

DELETE FROM original_table 
WHERE id IN(
    SELECT id FROM copy_table 
); 

自從我上次使用MySQL和SQL以來已經有一段時間了,所以我很確定有更好的性能 - 但這應該起作用;)