在MySQL中查找重复记录

Chr*_*tow 630 mysql duplicates

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

SELECT address, count(id) as cnt FROM list
GROUP BY address HAVING cnt > 1
Run Code Online (Sandbox Code Playgroud)

结果如下:

100 MAIN ST    2
Run Code Online (Sandbox Code Playgroud)

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

JIM    JONES    100 MAIN ST
JOHN   SMITH    100 MAIN ST
Run Code Online (Sandbox Code Playgroud)

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

Pow*_*ord 669

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

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;
Run Code Online (Sandbox Code Playgroud)

  • 小心查询.对于性能问题,子查询可能非常糟糕.如果这需要经常发生和/或有大量重复记录,我会考虑将处理从数据库移到数据集中. (67认同)
  • 使用此查询+1,您可以找到重复项,但也可以找到重复项,一式四份.....等等 (30认同)
  • 这是一个不相关的子查询,所以假设单独的查询设计不是很糟糕,那就不应该太糟糕了. (11认同)
  • @nick:关于子查询,它仍然是一个有效的点. (3认同)
  • 这是正确的想法,但同样如下,这只有在地址保证标准化的情况下才有效... (3认同)

小智 338

SELECT date FROM logs group by date having count(*) >= 2
Run Code Online (Sandbox Code Playgroud)

  • 小心这个答案.它只返回一个重复项.如果您有相同记录的2份以上,则不会全部看到它们,并且在删除所返回的记录后,您的表中仍会有重复项. (12认同)
  • 为什么`> = 2`?只需使用`HAVING COUNT(*)> 1` (6认同)
  • 这是与Laravel一起使用的最简单的工作查询.只需要在查询中添加` - >(DB :: raw('count(*)'),'>',2)`.非常感谢! (5认同)
  • @TerryLin 考虑到这实际上并没有解决最初提出的问题(即如何返回所有重复项),我不同意。 (2认同)
  • 有人可以向我解释一下为什么这会得到如此高的支持吗?它看起来几乎与原始问题中的第一个代码完全相同,提问者说这是不充分的。我缺少什么? (2认同)

rud*_*son 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
Run Code Online (Sandbox Code Playgroud)

如果地址可以存在两次以上,则需要DISTINCT.

  • 我也对此进行了测试,与我所接受的解决方案(最新的MySQL,120.000行的表)相比,它几乎慢了6倍.这可能是因为它需要一个临时表,在两者上运行EXPLAIN来查看差异. (20认同)
  • 我将查询的最后一部分更改为"WHERE a.id> b.id"以仅过滤掉较新的重复项,这样我就可以直接对结果执行"DELETE".切换比较以列出较旧的重复项. (3认同)

Arm*_*lik 53

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

SELECT COUNT(*) c,title FROM `data` GROUP BY title HAVING c > 1;
Run Code Online (Sandbox Code Playgroud)


小智 44

select `cityname` from `codcities` group by `cityname` having count(*)>=2
Run Code Online (Sandbox Code Playgroud)

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


dou*_*osh 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;
Run Code Online (Sandbox Code Playgroud)

  • 要查找实际的副本,您只需要内部查询.这比其他答案要快. (2认同)

Tud*_*dor 30

这不容易:

SELECT *
FROM tc_tariff_groups
GROUP BY group_id
HAVING COUNT(group_id) >1
Run Code Online (Sandbox Code Playgroud)


KES*_*MAN 20

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

SELECT COUNT(*), column1, column2 
FROM tablename
GROUP BY column1, column2
HAVING COUNT(*)>1;
Run Code Online (Sandbox Code Playgroud)


jer*_*ity 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
Run Code Online (Sandbox Code Playgroud)

在这种情况下你真正做的就是获取原始列表,创建两个p表 - p 1p 2 - 然后在地址列(第3行)上执行连接.第4行确保同一记录在您的结果集中不会多次显示("重复重复").


Mat*_*att 11

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

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

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

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

  • 用于查看匹配地址字符串所涉及的难度的+1,尽管您可能希望指定OP的"重复记录"问题本身并不复杂,但是在比较地址时 (5认同)

Cha*_*rch 10

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

SELECT *
FROM list AS outer
WHERE (SELECT COUNT(*)
        FROM list AS inner
        WHERE inner.address = outer.address) > 1;
Run Code Online (Sandbox Code Playgroud)


Qua*_*noi 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
Run Code Online (Sandbox Code Playgroud)

此查询可以模拟ROW_NUMBER()存在于Oracle和中SQL Server

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

  • 不要挑剔,但是`FROM(SELECT ...)aoo`是一个子查询:-P (19认同)

Mar*_*nev 7

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

SELECT  `Language` , id, COUNT( id ) AS how_many
FROM  `languages` 
GROUP BY  `Language` 
HAVING how_many >=2
ORDER BY how_many DESC
Run Code Online (Sandbox Code Playgroud)


小智 5

SELECT id, count(*) as c  
 FROM 'list'
GROUP BY id HAVING c > 1
Run Code Online (Sandbox Code Playgroud)

这将返回 id 以及该 id 重复的次数,或者返回任何内容,在这种情况下您将不会有重复的 id。

更改组中的 id(例如:地址),它将返回由第一个找到的 id 与该地址标识的地址重复的次数。

SELECT id, count(*) as c  
 FROM 'list'
GROUP BY address HAVING c > 1
Run Code Online (Sandbox Code Playgroud)

我希望它有帮助。享受 ;)