2010-08-01 34 views
14

Tôi có một bảng với các cột sau:Xóa các bản sao chỉ sử dụng truy vấn MySQL?

URL_ID  
URL_ADDR  
URL_Time 

Tôi muốn gỡ bỏ bản sao trên URL_ADDR cột sử dụng một truy vấn MySQL.

Có thể thực hiện một việc như vậy mà không cần sử dụng bất kỳ chương trình nào không?

+9

SQL đang lập trình ... –

+0

URL trong URL_ADDR trông như thế nào? Tất cả đều có cùng định dạng? tức là: có hoặc không có www. –

+0

không cùng định dạng. – Jim

Trả lời

0

Bạn có thể nhóm theo URL_ADDR sẽ chỉ cung cấp cho bạn các giá trị khác biệt duy nhất trong trường URL_ADDR.

select 
URL_ID 
URL_ADDR 
URL_Time 
from 
some_table 
group by 
URL_ADDR 

Tận hưởng!

+0

Truy vấn đó sẽ không hoạt động. –

5

này sẽ để lại cho những người thân với mức cao nhất URL_ID cho một cụ thể URL_ADDR

DELETE FROM table 
WHERE URL_ID NOT IN 
    (SELECT ID FROM 
     (SELECT MAX(URL_ID) AS ID 
     FROM table 
     WHERE URL_ID IS NOT NULL 
     GROUP BY URL_ADDR) X) /*Sounds like you would need to GROUP BY a 
            calculated form - e.g. using REPLACE to 
            strip out www see Daniel's answer*/ 

(Các nguồn gốc bảng 'X' là avoid the error "Bạn không thể chỉ định bảng mục tiêu 'tablename' để cập nhật trong mệnh đề FROM ")

+0

@Vilx: Đó là lý do tại sao bạn chôn nó trong một truy vấn phụ khác. –

3

Vâng, bạn có thể luôn:

  1. tạo ra một bảng tạm thời;
  2. INSERT INTO ... SELECT DISTINCT vào bảng tạm thời từ bảng gốc;
  3. rõ ràng ban đầu bảng
  4. INSERT INTO ... SELECT vào bảng gốc từ bảng tạm
  5. bảng thả temp.

Đó là vụng về và vụng về, và yêu cầu một số truy vấn (chưa kể đến đặc quyền), nhưng nó sẽ thực hiện thủ thuật nếu bạn không tìm thấy giải pháp khác.

30

Hãy xem xét các trường hợp thử nghiệm sau đây:

CREATE TABLE mytb (url_id int, url_addr varchar(100)); 

INSERT INTO mytb VALUES (1, 'www.google.com'); 
INSERT INTO mytb VALUES (2, 'www.microsoft.com'); 
INSERT INTO mytb VALUES (3, 'www.apple.com'); 
INSERT INTO mytb VALUES (4, 'www.google.com'); 
INSERT INTO mytb VALUES (5, 'www.cnn.com'); 
INSERT INTO mytb VALUES (6, 'www.apple.com'); 

đâu bảng thử nghiệm của chúng tôi bây giờ chứa:

SELECT * FROM mytb; 
+--------+-------------------+ 
| url_id | url_addr   | 
+--------+-------------------+ 
|  1 | www.google.com | 
|  2 | www.microsoft.com | 
|  3 | www.apple.com  | 
|  4 | www.google.com | 
|  5 | www.cnn.com  | 
|  6 | www.apple.com  | 
+--------+-------------------+ 
5 rows in set (0.00 sec) 

Sau đó chúng ta có thể sử dụng nhiều bảng DELETE cú pháp như sau:

DELETE t2 
FROM mytb t1 
JOIN mytb t2 ON (t2.url_addr = t1.url_addr AND t2.url_id > t1.url_id); 

... mà sẽ xóa các mục trùng lặp, chỉ để lại các url đầu tiên dựa trên url_id:

SELECT * FROM mytb; 
+--------+-------------------+ 
| url_id | url_addr   | 
+--------+-------------------+ 
|  1 | www.google.com | 
|  2 | www.microsoft.com | 
|  3 | www.apple.com  | 
|  5 | www.cnn.com  | 
+--------+-------------------+ 
3 rows in set (0.00 sec) 

CẬP NHẬT - Tiếp tục cho ý kiến ​​mới trên:

Nếu URL trùng lặp sẽ không có cùng định dạng, bạn có thể muốn áp dụng hàm REPLACE() để xóa các phần www. hoặc http://.Ví dụ:

DELETE t2 
FROM mytb t1 
JOIN mytb t2 ON (REPLACE(t2.url_addr, 'www.', '') = 
        REPLACE(t1.url_addr, 'www.', '') AND 
        t2.url_id > t1.url_id); 
+0

Vì vậy, JOIN sẽ không kích hoạt lỗi 1093? Cấp, một JOIN không phải là một truy vấn phụ nhưng tự tham chiếu là vấn đề thực sự .... –

+0

@OMG: Dường như nó không :) –

+0

+1 Để đề cập đến vấn đề 'REPLACE'. –

0

Điều này sẽ hoạt động với điều kiện cột URL_ID của bạn là duy nhất.

DELETE FROM url WHERE URL_ID IN (
SELECT URL_ID 
FROM url a INNER JOIN (
    SELECT URL_ADDR, MAX(URL_ID) MaxURLId 
    FROM url 
    GROUP BY URL_ADDR 
    HAVING COUNT(*) > 1) b ON a.URL_ID <> b.MaxURLId AND a.URL_ADDR = b.URL_ADDR 
) 
1

Daniel Vassallo Cách dùng cho nhiều cột?

DELETE t2 TỪ t1 directory1 THAM GIA directory1 t2 ON (t2.page = t1.page, t2.parentTopic = t1.parentTopic, t2.title = t1.title, t2.description = t1.description, t2. linktype = t1.linktype, t2.priority = t1.priority AND t2.linkID> t1.linkID);

có thể như thế này?

Các vấn đề liên quan