在MySQL中查找重复记录

问题描述 投票:611回答:22

我想在MySQL数据库中提取重复记录。这可以通过以下方式完成:

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

结果如下:

100 MAIN ST    2

我想拉它,以便它显示每一行是重复的。就像是:

JIM    JONES    100 MAIN ST
JOHN   SMITH    100 MAIN ST

有关如何做到这一点的任何想法?我试图避免做第一个,然后在代码中使用第二个查询查找重复项。

mysql duplicates
22个回答
649
投票

关键是重写此查询,以便它可以用作子查询。

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;

11
投票

查找重复地址要比看起来复杂得多,特别是如果您需要准确性。在这种情况下,MySQL查询是不够的......

我在SmartyStreets工作,我们在那里处理验证和重复数据删除以及其他问题,我看到了类似问题的许多不同挑战。

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

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


10
投票

这将在一个表传递中选择重复,没有子查询。

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

这个查询实际上模拟了ROW_NUMBER()和qazxsw poi中存在的qazxsw poi

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

  • Oracle - 在SQL Server模仿。

8
投票

不会非常有效,但它应该工作:

Analytic functions: SUM, AVG, ROW_NUMBER

7
投票

这也将显示有多少重复项,并将在没有连接的情况下对结果进行排序

MySQL

4
投票
SELECT *
FROM list AS outer
WHERE (SELECT COUNT(*)
        FROM list AS inner
        WHERE inner.address = outer.address) > 1;

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

对于你的桌子,它会是这样的

 SELECT firstname, lastname, address FROM list
 WHERE 
 Address in 
 (SELECT address FROM list
 GROUP BY address
 HAVING count(*) > 1)

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


4
投票

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

select * from table_name t1 inner join (select distinct <attribute list> from table_name as temp)t2 where t1.attribute_name = t2.attribute_name

4
投票

个人这个查询已经解决了我的问题:

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

此脚本的作用是显示在表中不止一次存在的所有订户ID以及找到的重复数。

这是表格列:

/* 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;

希望它对你有帮助!


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

用您的表替换城市。将名称替换为您的字段名称


2
投票
| 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    |                |

335
投票
SELECT date FROM logs group by date having count(*) >= 2

0
投票

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 确实是最好的,我建议再做一次更改:使用LIMIT确保db不会超载:

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

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



-1
投票

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

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


193
投票

为什么不只是INNER加入表自己?

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。


52
投票

我尝试了为这个问题选择的最佳答案,但它让我感到困惑。我实际上只需要在我的桌子上的一个字段上。来自this link的以下示例对我来说非常好:

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

42
投票
select `cityname` from `codcities` group by `cityname` having count(*)>=2

这是您要求的类似查询,其200%的工作也很容易。请享用!!!


35
投票

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

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;

21
投票

这不容易:

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

?


19
投票

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

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

13
投票

另一个解决方案是使用表别名,如下所示:

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行确保同一记录在您的结果集中不会多次显示(“重复重复”)。

© www.soinside.com 2019 - 2024. All rights reserved.