在MySQL中查找重复记录

Find duplicate records in MySQL

我想提取MySQL数据库中的重复记录。这可以通过以下方式实现:

1
2
SELECT address, count(id) as cnt FROM list
GROUP BY address HAVING cnt > 1

结果是:

1
100 MAIN ST    2

我想把它拉出来,这样它就可以显示每一行重复的内容。比如:

1
2
JIM    JONES    100 MAIN ST
JOHN   SMITH    100 MAIN ST

有什么想法可以这样做吗?我试图避免做第一个,然后用代码中的第二个查询查找重复项。


关键是重写此查询,以便将其用作子查询。

1
2
3
4
5
6
7
8
9
SELECT firstname,
   lastname,
   list.address
FROM list
   INNER JOIN (SELECT address
               FROM   list
               GROUP  BY address
               HAVING COUNT(id) > 1) dup
           ON list.address = dup.address;



为什么不直接用内部连接表本身呢?

1
2
3
4
SELECT a.firstname, a.lastname, a.address
FROM list a
INNER JOIN list b ON a.address = b.address
WHERE a.id <> b.id

如果地址可以存在两次以上,则需要distinct。


我试过为这个问题选择最好的答案,但有点困惑。实际上我只需要在我的表中的一个字段上使用它。下面这个链接中的示例对我来说非常有用:

1
SELECT COUNT(*) c,title FROM `data` GROUP BY title HAVING c > 1;


1
select `cityname` from `codcities` group by `cityname` having count(*)>=2

这是您所要求的类似查询,它的200%工作起来也很容易。享受!!!!


通过此查询的电子邮件地址查找重复用户…

1
2
3
4
5
6
7
8
9
SELECT users.name, users.uid, users.mail, from_unixtime(created)
FROM users
INNER JOIN (
  SELECT mail
  FROM users
  GROUP BY mail
  HAVING count(mail) > 1
) dupes ON users.mail = dupes.mail
ORDER BY users.mail;


这不容易吗:

1
2
3
4
SELECT *
FROM tc_tariff_groups
GROUP BY group_id
HAVING COUNT(group_id) >1


我们发现重复项也依赖于多个字段。对于这些情况,您可以使用下面的格式。

1
2
3
4
SELECT COUNT(*), column1, column2
FROM tablename
GROUP BY column1, column2
HAVING COUNT(*)>1;


另一种解决方案是使用表别名,如:

1
2
3
4
SELECT p1.id, p2.id, p1.address
FROM list AS p1, list AS p2
WHERE p1.address = p2.address
AND p1.id != p2.id

在本例中,您真正要做的就是提取原始列表表,创建两个模拟表(p1和p2),然后在地址列(第3行)上执行联接。第4行确保同一记录不会在结果集中多次显示("重复副本")。


查找重复地址比看起来要复杂得多,尤其是在需要精确性的情况下。在这种情况下,mysql查询是不够的…

我在SmartyStreets工作,在那里我们解决验证、重复数据消除和其他问题,我已经看到了许多具有类似问题的不同挑战。

有几个第三方服务将在列表中为您标记重复项。单独使用MySQL子查询进行此操作不会考虑地址格式和标准的差异。USPS(美国地址)有制定这些标准的某些指导方针,但只有少数供应商获得了执行此类操作的认证。

因此,我建议您最好的答案是将表导出到一个csv文件中,然后将其提交给一个有能力的列表处理器。其中之一就是LiveAddress,它将在几秒钟到几分钟内自动为您完成。它将用一个名为"duplicate"的新字段标记重复的行,其中的值为Y


不会很有效率,但它应该可以工作:

1
2
3
4
5
SELECT *
FROM list AS outer
WHERE (SELECT COUNT(*)
        FROM list AS inner
        WHERE inner.address = outer.address) > 1;

这将在一个表传递中选择重复项,而不选择子查询。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SELECT  *
FROM    (
        SELECT  ao.*, (@r := @r + 1) AS rn
        FROM    (
                SELECT  @_address := 'N'
                ) vars,
                (
                SELECT  *
                FROM
                        list a
                ORDER BY
                        address, id
                ) ao
        WHERE   CASE WHEN @_address <> address THEN @r := 0 ELSE 0 END IS NOT NULL
                AND (@_address := address ) IS NOT NULL
        ) aoo
WHERE   rn > 1

这个查询实际上模拟了OracleSQL Server中的ROW_NUMBER()

有关详细信息,请参阅我的博客中的文章:

  • 分析函数:MySQL中的和、平均、行数模拟。


这还将显示有多少个重复项,并将排序不带联接的结果。

1
2
3
4
5
SELECT  `Language` , id, COUNT( id ) AS how_many
FROM  `languages`
GROUP BY  `Language`
HAVING how_many >=2
ORDER BY how_many DESC


最快的重复删除查询过程:

1
2
3
4
/* create temp table with one primary column id */
INSERT INTO temp(id) SELECT MIN(id) FROM list GROUP BY (isbn) HAVING COUNT(*)>1;
DELETE FROM list WHERE id IN (SELECT id FROM temp);
DELETE FROM temp;


就个人而言,这个问题解决了我的问题:

1
SELECT `SUB_ID`, COUNT(SRV_KW_ID) as subscriptions FROM `SUB_SUBSCR` group by SUB_ID, SRV_KW_ID HAVING subscriptions > 1;

此脚本所做的是显示表中存在多次的所有订阅服务器ID以及找到的重复项数量。

这是表列:

1
2
3
4
| SUB_SUBSCR_ID | int(11)     | NO   | PRI | NULL    | auto_increment |
| MSI_ALIAS     | varchar(64) | YES  | UNI | NULL    |                |
| SUB_ID        | int(11)     | NO   | MUL | NULL    |                |    
| SRV_KW_ID     | int(11)     | NO   | MUL | NULL    |                |

希望对您也有帮助!


1
2
3
4
5
6
 SELECT firstname, lastname, address FROM list
 WHERE
 Address in
 (SELECT address FROM list
 GROUP BY address
 HAVING count(*) > 1)


1
select * from table_name t1 inner join (select distinct  from table_name as temp)t2 where t1.attribute_name = t2.attribute_name

对于你的桌子来说

1
select * from list l1 inner join (select distinct address from list as list2)l2 where l1.address=l2.address

此查询将为您提供列表表中所有不同的地址条目…如果您对name等有任何主键值,我不确定这将如何工作。


1
SELECT t.*,(select count(*) from city as tt where tt.name=t.name) as count FROM `city` as t where (select count(*) from city as tt where tt.name=t.name) > 1 order by count desc

用你的桌子替换城市。将名称替换为域名


1
2
3
4
5
    SELECT *
    FROM (SELECT  address, COUNT(id) AS cnt
    FROM list
    GROUP BY address
    HAVING ( COUNT(id) > 1 ))


PowerLord的答案确实是最好的,我建议您再做一次更改:使用限制以确保DB不会过载:

1
2
3
4
SELECT firstname, lastname, list.address FROM list
INNER JOIN (SELECT address FROM list
GROUP BY address HAVING count(id) > 1) dup ON list.address = dup.address
LIMIT 10

如果没有连接的位置和时间,使用限制是一个好习惯。从小值开始,检查查询有多重,然后增加限制。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    Find duplicate Records:

    Suppose we have table : Student
    student_id int
    student_name varchar
    Records:
    +------------+---------------------+
    | student_id | student_name        |
    +------------+---------------------+
    |        101 | usman               |
    |        101 | usman               |
    |        101 | usman               |
    |        102 | usmanyaqoob         |
    |        103 | muhammadusmanyaqoob |
    |        103 | muhammadusmanyaqoob |
    +------------+---------------------+

    Now we want to see duplicate records
    Use this query:


   select student_name,student_id ,count(*) c from student group by student_id,student_name having c>1;

+--------------------+------------+---+
| student_name        | student_id | c |
+---------------------+------------+---+
| usman               |        101 | 3 |
| muhammadusmanyaqoob |        103 | 2 |
+---------------------+------------+---+

埃多克斯1〔5〕

内部子查询返回地址重复的行,然后外部子查询返回重复地址的地址列。外部子查询只能返回一列,因为它用作运算符"=any"的操作数。