2012-10-28 127 views
2

我有一些需要删除冗余数据的MySQL表。例如:选择具有重复数据的行

id email   date  data... 
1 [email protected] 2012-01-01 my_data 
2 [email protected] 2012-01-01 my_data 
3 [email protected] 2012-01-02 my_data 
4 [email protected] 2012-01-02 my_data (redundant) 
5 [email protected] 2012-01-02 my_data 

我需要删除多余的行,但我想先选择它们。我发现这个StackOverflow上,但它需要的电子邮件地址

SELECT * 
FROM `my_table` 
WHERE `id` IN (SELECT `id` 
       FROM `my_table` 
       where `email` = '[email protected]' 
       group by `date` 
       HAVING count(*) > 1) 

我可以使用什么样的查询像上面在嵌入式查询不使用WHERE预选赛,所以我能做到这一点下跌的所有电子邮件地址?

该查询可以是一个SELECT查询。我不介意在PHPMyAdmin中手动删除行。

+0

''' '我可以像上面那样在嵌入式查询中不使用WHERE限定符来使用什么查询,这样我就可以执行所有电子邮件地址了? '''通过这个你是否意味着所有重复的,只是保持一个副本? –

+0

是的,删除所有重复的行,但保留原始行 –

回答

7
DELETE FROM tableName 
WHERE ID NOT IN 
(
    SELECT minID 
    FROM 
    (
     SELECT email, date, MIN(id) minID 
     FROM tableNAme 
     GROUP BY email, date 
    ) x 
) 

或通过使用JOIN

DELETE a 
FROM tableName a 
    LEFT JOIN (
      SELECT minID 
      FROM (
        SELECT email, DATE, MIN(id) minID 
        FROM tableNAme 
        GROUP BY email, DATE 
        ) y 
      ) x 
      ON a.ID = x.minID 
WHERE x.minID IS NULL; 

下面的查询只SELECT每个电子邮件日期重复的行

SELECT a.* 
FROM tableName a 
     LEFT JOIN 
     ( 
     SELECT minID 
     FROM 
     (
      SELECT email, date, MIN(id) minID 
      FROM tableNAme 
      GROUP BY email, date 
     )y 
     ) x ON a.ID = x.minID 
WHERE x.minID IS NULL 
+1

出色的工作... :) – Sami

+2

约翰值得双倍积分,因为他完美地回答了它,并将我介绍给SQL小提琴!真棒! –

0

另一种方法是计算日期列的出现次数为每个电子邮件地址在你的桌子上:

SELECT `email`, `date`, COUNT(*) FROM `my_table` GROUP BY `date`, `email` HAVING COUNT(*) > 1 

+------------------+---------------------+----------+ 
| email   | date    | COUNT(*) | 
+------------------+---------------------+----------+ 
| [email protected] | 2012-01-02 00:00:00 |  2 | 
+------------------+---------------------+----------+ 
+0

但是,我必须为每个电子邮件地址执行此操作。 –

+0

@EricCope我从您的示例数据中输出了这个查询输出,但是如果您有很多电子邮件,它会自动显示所有电子邮件,每天操作时count> 1。您还必须记住要删除的行的限制,即在上面的计数为2的情况下,所以您只能删除一行,而不是两个(!)。因此,在一个非常安全的方面,你可以重写我的查询为: '选择电子邮件,日期,计数(*)作为'计数', CONCAT('删除我的电子邮件地址='',电子邮件' ''LIMIT',(COUNT(*) - 1),';')AS'query' FROM my_table GROUP BY date,email HAVING COUNT(*)> 1; – GregD