2010-09-08 9 views
13

Tôi có một bảng dữ liệu và có nhiều mục trùng lặp từ nội dung gửi của người dùng.Xóa các hàng trùng lặp để lại hàng cũ nhất Chỉ có?

Tôi muốn xóa tất cả các hàng trùng dựa trên các lĩnh vực subscriberEmail, chỉ để lại trình gốc.

Nói cách khác, tôi muốn tìm kiếm tất cả các email trùng lặp và xóa những hàng, chỉ để lại bản gốc.

Tôi làm cách nào để thực hiện việc này mà không cần hoán đổi bảng?
Bảng của tôi chứa các ID duy nhất cho mỗi hàng.

+0

Bạn nên đánh dấu câu trả lời là "đã chấp nhận" :-) – watery

Trả lời

27

Vì bạn đang sử dụng cột id như một chỉ số mà kỷ lục là 'gốc':

delete x 
from myTable x 
join myTable z on x.subscriberEmail = z.subscriberEmail 
where x.id > z.id 

này sẽ để lại một bản ghi cho mỗi địa chỉ email.

chỉnh sửa để thêm:

Để giải thích các truy vấn trên ...

Ý tưởng ở đây là để tham gia vào bảng chống lại chính nó. Giả vờ rằng bạn có hai bản sao của bảng, mỗi bản được đặt tên khác nhau. Sau đó, bạn có thể so sánh chúng với nhau và tìm id thấp nhất hoặc cho từng địa chỉ email. Sau đó, bạn sẽ thấy các bản ghi trùng lặp được tạo sau này và có thể xóa chúng. (Tôi đã hình dung Excel khi suy nghĩ về điều này.)

Để thực hiện thao tác đó trên bàn, so sánh nó với chính nó và có thể xác định mỗi bên, bạn sử dụng bí danh bảng. x là bí danh bảng. Nó được gán trong mệnh đề from như sau: from <table> <alias>. x hiện có thể được sử dụng ở nơi khác trong cùng một truy vấn để tham chiếu đến bảng đó dưới dạng lối tắt.

delete x bắt đầu truy vấn đầu với hành động và mục tiêu của chúng tôi. Chúng tôi sẽ thực hiện một truy vấn để chọn các bản ghi từ nhiều bảng và chúng tôi muốn xóa các bản ghi xuất hiện trong x.

biệt hiệu được sử dụng để tham khảo cả 'trường hợp' của bảng. from myTable x join myTable z on x.subscriberEmail = z.subscriberEmail chạm vào bảng để chống lại chính nó, nơi các email khớp với nhau. Không có mệnh đề where sau đó, mọi bản ghi sẽ được chọn vì nó có thể được nối với chính nó.

Mệnh where giới hạn các hồ sơ được chọn. where x.id > z.id cho phép 'mẫu' được đặt tên là x để chỉ chứa các bản ghi khớp với email nhưng có giá trị cao hơn id. Dữ liệu mà bạn thực sự muốn trong bảng, địa chỉ email duy nhất (có id thấp nhất) sẽ không là một phần của x và sẽ không bị xóa. Các hồ sơ duy nhất trong x sẽ là bản ghi trùng lặp (địa chỉ email) có số cao hơn id so với bản ghi gốc cho địa chỉ email đó.

Các tham gia và nơi điều khoản có thể được kết hợp trong trường hợp này:

delete x 
    from myTable x 
    join myTable z 
    on x.subscriberEmail = z.subscriberEmail 
     and x.id > z.id 

Để ngăn chặn bản sao, hãy xem xét làm cột subscriberEmail một cột được lập chỉ mục UNIQUE.

+0

Xin chào, tôi không hiểu X là gì và tại đây ngày tháng được nhập. Tôi có thể sử dụng ID vì có ID chính được đặt cho mỗi ngày hoặc ngày. ID âm thanh dễ dàng hơn –

+0

Hey, nó đã hoạt động !!! Tôi đã thay đổi "createdOn" thành "id" và mau! haha cảm ơn - Heres mã tôi đã sử dụng trong PHP: mysql_query ("xóa x từ my_Table x tham gia my_Table z trên x.subscriberEmail = z.subscriberEmail nơi x.id> z.id") or die (mysql_error ()); –

+0

Bạn có thể giải thích cách đọc mã này bằng tiếng Anh không - nó giúp có thể đọc một cách hợp lý một cái gì đó để hiểu cú pháp - Ngoài ra, bây giờ làm thế nào để ngăn chặn các bản sao ở nơi đầu tiên? Tôi đã sử dụng Chèn IGNORE nhưng nó không bỏ qua –

0

Nếu bạn có một id duy nhất cho mỗi hàng, bạn có thể thử một cái gì đó như thế này. Đừng hỏi tôi tại sao chính xác bạn cần câu lệnh chọn thứ hai, mysql sẽ không cho phép tôi thực thi khác. Ngoài ra, nhóm theo bất kỳ cột nào làm cho kết quả của bạn trở nên độc đáo.

delete from my_table where id in (
    select id from (
    select id from my_table a group by subscriberEmail having count(*) > 1 
) b 
); 
+1

Tôi tin rằng điều này sẽ xóa tất cả chúng, không chỉ các tính năng bổ sung. – Fosco

+0

Không, không. Nhóm theo nhóm sẽ giống như các hàng theo subscriberEmail. Vì vậy, người đăng ký có nhiều hơn 1 email sẽ được chọn (có số (*)> 1). Tại thời điểm này, bạn có khá nhiều bộ hồ sơ đăng ký riêng biệt với hơn 1 email. Lấy ID từ bộ hồ sơ này và xóa nó đi. Tôi đã thử nó và nó hoạt động như một sự quyến rũ. –

+0

Chạy mã này tạo lỗi "# 1064 - Bạn có lỗi trong cú pháp SQL của bạn; kiểm tra hướng dẫn tương ứng với phiên bản máy chủ MySQL của bạn để sử dụng đúng cú pháp" ở dòng 2 "- Mã dưới đây –

1

Làm thế nào về vấn đề này, bây giờ bạn không cần phải tạo ra bất kỳ bảng tạm thời sử dụng tự tham gia

DELETE u1 FROM users u1, users u2 WHERE u1.id < u2.id AND u1.email = u2.email 

Để kiểm tra xem có bất kỳ bản ghi trùng lặp trong bảng

SELECT count(*) as Count, email FROM users u group by email having Count > 1