2012-12-26 35 views
42

Tôi đã thấy một số biến thể về điều này nhưng không có gì phù hợp với những gì tôi đang cố gắng thực hiện.Làm cách nào để xóa tất cả các bản ghi trùng lặp trong bảng MySQL mà không có các bảng tạm thời

Tôi có một bảng, TableA, chứa các câu trả lời do người dùng đưa ra cho các bảng câu hỏi có thể cấu hình. Các cột là member_id, quiz_num, question_num, answer_num.

Bằng cách nào đó một số thành viên đã nhận được câu trả lời của họ được gửi hai lần. Vì vậy, tôi cần phải loại bỏ các bản ghi trùng lặp, nhưng chắc chắn rằng một hàng còn lại phía sau. Không có cột "chính" để có thể có hai hoặc ba hàng với cùng một dữ liệu chính xác.

Có truy vấn để xóa tất cả các bản sao không?

+0

Có lý do nào bạn chống lại việc tạo bảng tạm thời có thể bị xóa với tuyên bố bảng thả đơn giản sau khi các bản sao đã bị xóa không? Tôi có thể cung cấp cho bạn SQL để tạo ra một bảng tạm thời với các bản ghi duy nhất, xóa các bản ghi từ bảng gốc, tải dữ liệu duy nhất rồi thả bảng tạm thời. Nếu nó không phải là một cơ sở dữ liệu lớn, điều này sẽ không mất quá nhiều thời gian. Dưới đây là một bài viết hay về quy trình: http://www.databasejournal.com/features/mysql/article.php/10897_2201621_2/Deleting-Duplicate-Rows-in-a-MySQL-Database.htm – Kyle

+0

bản sao có thể có của [Cách thực hiện xóa bản ghi trùng lặp trong cơ sở dữ liệu mysql?] (http://stackoverflow.com/questions/659906/how-to-delete-duplicate-records-in-mysql-database) –

+0

Tôi đang tìm một giải pháp dễ dàng (trong ý nghĩa rộng nhất của từ) lặp lại khi đang di chuyển. Sử dụng thêm bảng, tạm thời hoặc không, có nghĩa là đưa xuống trang web bất cứ lúc nào điều này được phát hiện. Giải pháp tốt nhất là đảm bảo nó không bao giờ xảy ra ngay từ đầu, nhưng cho đến lúc đó, tôi muốn kiểm tra/sửa lỗi này được thực hiện thường xuyên để đảm bảo các báo cáo không mang lại kết quả khả quan – MivaScott

Trả lời

98

Thêm Index Unique trên bàn của bạn:

ALTER IGNORE TABLE `TableA` 
ADD UNIQUE INDEX (`member_id`, `quiz_num`, `question_num`, `answer_num`); 

Một cách khác để làm điều này sẽ be:

Thêm khóa chính trong bảng của bạn, sau đó bạn có thể dễ dàng xóa các từ khóa trùng lặp khỏi bảng của mình bằng truy vấn sau:

DELETE FROM member 
WHERE id IN (SELECT * 
      FROM (SELECT id FROM member 
        GROUP BY member_id, quiz_num, question_num, answer_num HAVING (COUNT(*) > 1) 
       ) AS A 
      ); 
+0

Tôi sẽ tiếp tục và chọn điều này làm câu trả lời.Cuối cùng tôi sẽ phải sử dụng một bảng tạm thời để dọn dẹp nhà cửa, nhưng tôi sẽ đảm bảo thêm UNIQUE INDEX để không có vấn đề này trong tương lai. Bây giờ tôi chỉ cần tìm ra cách mọi thứ đã được nhân đôi ngay từ đầu. – MivaScott

+0

Nội dung tuyệt vời !!!! Cảm ơn rất nhiều! :) – Karma

+0

@KarmicDice Bạn được chào đón nhiều nhất ... –

12

Điều này không sử dụng Bảng TEMP, mà là bảng thực thay thế. Nếu vấn đề chỉ là về các bảng tạm thời và không phải là về tạo bảng hoặc bảng giảm, điều này sẽ làm việc:

SELECT DISTINCT * INTO TableA_Verify FROM TableA; 

DROP TABLE TableA; 

RENAME TABLE TableA_Verify TO TableA; 
13

Thay vì drop table TableA, bạn có thể xóa tất cả các thanh ghi (delete from TableA;) và sau đó điền bảng gốc với sổ đăng ký đến từ TableA_Verify (insert into TAbleA select * from TAbleA_Verify). Bằng cách này bạn sẽ không bị mất tất cả các tham chiếu đến bảng gốc (chỉ số, ...)

CREATE TABLE TableA_Verify AS SELECT DISTINCT * FROM TableA;

DELETE FROM TableA;

INSERT INTO TableA SELECT * FROM TAbleA_Verify;

DROP TABLE TableA_Verify;

6

Nhờ jveirasv cho câu trả lời ở trên.

Nếu bạn cần phải loại bỏ các bản sao của một bộ cụ thể của cột, bạn có thể sử dụng (nếu bạn có một dấu thời gian trong bảng mà thay đổi ví dụ)

CREATE TABLE TableA_Verify AS SELECT * FROM TableA WHERE 1 GROUP BY [COLUMN TO remove duplicates BY];

DELETE FROM TableA;

INSERT INTO TableA SELECT * FROM TAbleA_Verify;

DROP TABLE TableA_Verify;

6

Thêm Uni que Index trên bàn của bạn:

ALTER IGNORE TABLE TableA 
ADD UNIQUE INDEX (member_id, quiz_num, question_num, answer_num); 

là hoạt động rất tốt

+0

cảm ơn bạn, nó hoạt động, nhưng tôi nhận được 1 cảnh báo: 1681 'IGNORE' không còn được dùng nữa và sẽ bị xóa trong bản phát hành sau này. Bản sao: 1 Cảnh báo: 1 – Lebnik

2

Nếu bạn không sử dụng bất kỳ khóa chính, sau đó thực hiện các truy vấn sau đây tại một nét duy nhất.Bởi các giá trị thay thế:

# table_name - Your Table Name 
# column_name_of_duplicates - Name of column where duplicate entries are found 

create table table_name_temp like table_name; 
insert into table_name_temp select distinct(column_name_of_duplicates),value,type from table_name group by column_name_of_duplicates; 
delete from table_name; 
insert into table_name select * from table_name_temp; 
drop table table_name_temp 
  1. tạo bảng tạm thời và lưu trữ riêng biệt (không trùng lặp) đánh giá cao
  2. làm trống bảng gốc
  3. giá trị chèn vào bảng gốc từ bảng temp
  4. bảng temp xóa

Bạn luôn nên sao lưu cơ sở dữ liệu trước khi chơi với nó.

0

Như đã nêu trong nhận xét, truy vấn trong câu trả lời của Saharsh Shah phải được chạy nhiều lần nếu các mục được nhân đôi nhiều lần.

Dưới đây là một giải pháp mà không xóa bất kỳ dữ liệu, và giữ cho dữ liệu trong bảng ban đầu trong suốt thời gian, cho phép các bản sao bị xóa trong khi vẫn giữ bàn 'sống':

alter table tableA add column duplicate tinyint(1) not null default '0'; 

update tableA set 
duplicate=if(@member_id=member_id 
      and @quiz_num=quiz_num 
      and @question_num=question_num 
      and @answer_num=answer_num,1,0), 
member_id=(@member_id:=member_id), 
quiz_num=(@quiz_num:=quiz_num), 
question_num=(@question_num:=question_num), 
answer_num=(@answer_num:=answer_num) 
order by member_id, quiz_num, question_num, answer_num; 

delete from tableA where duplicate=1; 

alter table tableA drop column duplicate; 

này về cơ bản kiểm tra xem hàng hiện tại có giống với hàng cuối cùng không và nếu có, đánh dấu nó là trùng lặp (câu lệnh thứ tự đảm bảo rằng các bản sao sẽ hiển thị bên cạnh nhau). Sau đó, bạn xóa các bản ghi trùng lặp. Tôi xóa cột duplicate ở cuối để đưa trở lại trạng thái ban đầu.

Dường như alter table ignore cũng có thể biến mất sớm: http://dev.mysql.com/worklog/task/?id=7395

0

Một cách khác là tạo ra một bảng tạm thời mới với cùng một cấu trúc.

CREATE TABLE temp_table AS SELECT * FROM original_table LIMIT 0 

Sau đó, tạo khóa chính trong bảng.

ALTER TABLE temp_table ADD PRIMARY KEY (primary-key-field) 

Cuối cùng sao chép tất cả bản ghi từ bảng gốc trong khi bỏ qua các bản ghi trùng lặp.

INSERT IGNORE INTO temp_table AS SELECT * FROM original_table 

Bây giờ bạn có thể xóa bảng gốc và đổi tên bảng mới.

DROP TABLE original_table 
RENAME TABLE temp_table TO original_table 
Các vấn đề liên quan