【问题标题】:Check Status of the Duplicate Records检查重复记录的状态
【发布时间】:2013-07-18 10:49:44
【问题描述】:

假设我们有一个名为 record 的表,其中包含 4 个字段

id    (INT 11 AUTO_INC)

email (VAR 50)

timestamp (INT 11)

status (INT 1)

并且该表包含以下数据

现在我们可以看到电子邮件地址 test@xample.com 被重复了 4 次(时间戳最低的记录是原始记录,之后的所有副本都是重复的)。我可以使用

轻松计算唯一记录的数量
SELECT COUNT(DISTINCT email) FROM record

我还可以轻松找出哪个电子邮件地址重复了多少次

SELECT email, count(id) FROM record GROUP BY email HAVING COUNT(id)>1

但现在的业务问题是

在所有重复记录中STATUS 有多少次是 1?

例如:

  • 对于 test@example.com,没有状态为 1 的重复记录
  • 对于 second@example.com,有 1 条状态为 1 的重复记录
  • 对于 third@example.com,有 1 条状态为 1 的重复记录
  • 对于four@example.com,没有状态为1 的重复记录
  • 对于 Five@example.com,有 2 条重复记录的状态为 1

所以所有数字的总和是0 + 1 + 1 + 0 + 2 = 4

这意味着有 4 条重复记录,其中 status = 1 在表中

问题

有多少 Duplicate 记录的 status = 1 ?

【问题讨论】:

  • 考虑提供一个 sqlfiddle(或者适当的 ddls)
  • 关于您的答案 stackoverflow.com/a/18307508/285587 的临时评论 - () 上带有数组的这件事是不正确的,而您的答案在技术上是正确的。
  • @YourCommonSense 谢谢,我知道从 5.5 开始,() 概念可用于访问数组值,因此我删除了我的答案并赞成你的。再次感谢:)
  • 除了一条不可靠的评论之外,您有任何证据吗?
  • 这是一个非常好的问题,而令人尴尬的答案是我认为该评论是有效的而没有做任何研究。似乎找不到任何关于我在那里被告知的内容

标签: mysql select duplicates


【解决方案1】:

这是一种效果更好的新解决方案。它会删除每封电子邮件的第一个条目,然后计算其余条目。这不容易阅读,如果可能的话我会把它写在一个存储过程中,但这很有效。

select sum(status)
  from dude d1
  join (select email, 
               min(ts) as ts 
          from dude 
         group by email) mins 
 using (email)
 where d1.ts != mins.ts;

sqlfiddle

下面的原始答案

您自己的查询来查找“哪个电子邮件地址被重复使用了多少次”

SELECT email, 
       count(id) as duplicates 
  FROM record 
 GROUP BY email 
HAVING COUNT(id)>1

可以轻松修改为回答“有多少重复记录的状态 = 1”

SELECT email, 
       count(id) as duplicates_status_sum 
  FROM record 
 GROUP BY email 
 WHERE status = 1 
HAVING COUNT(id)>1

这两个查询都将回答包括原始行,因此它实际上是“包括原始行的重复项”。如果原始状态始终为 1,则可以从总和中减去 1。

SELECT email, 
       count(id) -1 as true_duplicates 
  FROM record 
 GROUP BY email 
HAVING COUNT(id)>1

SELECT email, 
       count(id) -1 as true_duplicates_status_sum 
  FROM record 
 GROUP BY email 
 WHERE status = 1 
HAVING COUNT(id)>1

【讨论】:

  • 谢谢安德烈亚斯,这将分别给出每个电子邮件地址的数字。我需要获取符合条件的所有此类记录的数量,而不是在输出中按电子邮件分组。所以我想说 1000 条重复记录的状态 = 1,不按电子邮件分组,因为有数千个电子邮件地址
  • 我们怎么知道如果我们做 count(id)-1 我们将排除原始记录?因为我们没有在此查询中指定要排除哪一个。这可以包括原始的并排除重复的:)
【解决方案2】:

如果我的理解没有错,那么您的查询应该是

SELECT  `email` , COUNT(  `id` ) AS  `tot` 
FROM  `record` , (
SELECT  `email` AS  `emt` , MIN(  `timestamp` ) AS  `mtm` 
FROM  `record` 
GROUP BY  `email`
) AS  `temp` 
WHERE  `email` =  `emt` 
AND  `timestamp` >  `mtm` 
AND  `status` =1
GROUP BY  `email` 
HAVING COUNT(  `id` ) >=1

首先我们需要获取最小时间戳,然后找到在此时间戳之后插入且状态为 1 的重复记录。

如果你想要总和那么查询是

SELECT SUM(  `tot` ) AS  `duplicatesWithStatus1` 
FROM (
SELECT  `email` , COUNT(  `id` ) AS  `tot` 
FROM  `record` , (
SELECT  `email` AS  `emt` , MIN(  `timestamp` ) AS  `mtm` 
FROM  `record` 
GROUP BY  `email`
) AS  `temp` 
WHERE  `email` =  `emt` 
AND  `timestamp` >  `mtm` 
AND  `status` =1
GROUP BY  `email` 
HAVING COUNT(  `id` ) >=1
) AS t

希望这是你想要的

【讨论】:

  • 谢谢 Suraj,它似乎没有丢弃原始记录,我只需要获取重复的编号,而不是全部
  • 我已经编辑了我的答案,因为您需要排除原始答案,所以我将查询从 count(id) 更改为 count(id)-1
  • 我们怎么知道如果我们做 count(id)-1 我们将排除原始记录?因为我们没有在此查询中指定要排除哪一个。这可以包括原始的并排除重复的:)
  • 我认为您必须先对时间戳表中的值进行排序,然后再进行操作。
  • 对不起@Ø Hanky Panky Ø 我错过了您需要排除原始记录的部分。现在修改了查询。
【解决方案3】:

您可以通过

获得status = 1的重复记录的计数
select count(*) as Duplicate_Record_Count
from (select *
from record r
where r.status=1
group by r.email,r.status
having count(r.email)>1 ) t1

以下查询将返回具有状态 1 计数和时间戳的重复电子邮件

select  r.email,count(*)-1 as Duplicate_Count,min(r.timestamp) as timestamp
from record r
where r.status=1
group by r.email
having count(r.email)>1 

【讨论】:

  • 是否只考虑重复记录而忽略原始记录?
  • 我已经编辑了我的答案,第一个查询将只返回一个计数,第二个查询将返回您的重复电子邮件与计数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-16
  • 2013-10-23
  • 2020-03-28
  • 2014-06-27
  • 2022-12-06
  • 2018-01-02
相关资源
最近更新 更多