在MySql中查找重复的电子邮件,并根据条件删除某些电子邮件

时间:2014-11-03 04:19:58

标签: mysql sql mysqli coldfusion duplicate-removal

我看到很多方法可以找到重复的记录并删除它们,但我找不到我要找的那个,即根据某些条件删除它们。

下面从另一篇文章中获取的第一个SQL代码在查找重复项时效果很好。但是,我在第二部分遇到了问题。

<cfquery datasource="mydatabase" name="duplist">
SELECT  a.*, b.totalCount AS Duplicate
FROM    mytable a
        INNER JOIN
        (
            SELECT  email, COUNT(*) totalCount
            FROM    mytable
            GROUP   BY email
            HAVING  COUNT(*) > 1
        ) b ON a.email = b.email
</cfquery>

<cfoutput query="duplist">
    <CFQUERY DATASOURCE="mydatabase" name="dlist">
    SELECT * FROM mytable
    WHERE userid = '#userid#'
    AND activedate is null
    </CFQUERY>
</cfoutput> 

<cfoutput>
Total To Be Deleted: #dlist.recordcount#
</cfoutput>

我正在尝试使用SELECT(在用DELETE替换它之前)只复制那些没有&#34; activedate&#34;的用户电子邮件。基于输出查询&#34; duplist&#34;有重复的电子邮件记录。我只获得一条记录(#dlist.recordcount#),这是最后一条记录!问题不应该遍及它们吗?

编辑:

经过一些反馈并检查记录计数是否正确计数,因为它在循环之外。它可以在没有startdate的情况下检索那些记录。但是,现在真正的问题出现在以下情形中:

ID   USERID   EMAIL          STARTDATE
1    user1    test@test.com 
2    user2    test@test.com  11/01/2014
3    user3    test@test.com 
4    user4    test@test.com  11/02/2014 
5    user5    me@mydomain.com
6    user6    me@mydomain.com

运行上述代码将列出重复电子邮件的这6条记录。第二个查询将选择(删除)没有startdate的那些,即记录1,3,5和6.两个问题:

  1. 记录1和3将被删除,但2和4仍然是重复的
  2. 记录5和6将被删除,我没有用户收到电子邮件。我需要保留其中一个。
  3. 如何修改代码以处理方案?我想保留#4和#6的记录,因为4比2更新,6比6更新。

    4    user4    test@test.com  11/02/2014 
    6    user6    me@mydomain.com
    

4 个答案:

答案 0 :(得分:1)


您可以在查询中使用 IN 子句。但首先,您需要创建一个您将要传递到第二个查询的userId列表。您可以使用valueList这样做

<cfset userIdList = valueList(duplist.userId) />

然后在您的查询中传递该列表,如此

<CFQUERY DATASOURCE="mydatabase" name="dlist">
    SELECT * FROM myTable WHERE userId IN (#userIdList#) AND activeDate is null
<CFQUERY>

答案 1 :(得分:1)

这可以在单个查询中完成

<CFQUERY DATASOURCE="mydatabase" name="dlist">
 SELECT * FROM myTable 
 WHERE userId IN (SELECT userId
    FROM    mytable 
    GROUP   BY email
    HAVING  COUNT(email) > 1
   ) 
   AND activeDate is null
<CFQUERY>

答案 2 :(得分:1)

这是您的原始查询:

SELECT  a.*, b.totalCount AS Duplicate
FROM    mytable a
    INNER JOIN
    (
        SELECT  email, COUNT(*) totalCount
        FROM    mytable
        GROUP   BY email
        HAVING  COUNT(*) > 1
    ) b ON a.email = b.email

您需要做的就是添加:

where a.activeDate is null

你有你的记录。然后,一旦你看到它们,用你的select子句替换单词&#34; delete&#34;

编辑从这里开始

由于这仍然会留下重复,因此在执行上述操作后,请执行以下操作:

select id, email -- can be changed to delete after
from myTable deleteFrom join myTable keep on deleteFrom.email = keep.email
where deleteFrom.id < keep.id

这将保持最新记录。

答案 3 :(得分:1)

您可以使用Rank()函数对数据进行排名,并删除未排名为1的行。

Oracle相当于Rank()查询选择#4和#6数据:

SELECT * FROM
(
SELECT USERNAME, EMAIL, START_DATE, 
        RANK() OVER (PARTITION BY EMAIL ORDER BY START_DATE DESC NULLS LAST, ROWNUM DESC) AS RANK
FROM TEMP_SOL
)
WHERE RANK = 1

可以使用此链接Rank function in MySQL with Order By clause

派生等效的Mysql

编辑:非排名解决方案可能类似于:

首先获取所有重复的电子邮件

<cfquery name="dupEmail" datasource="XXX">
SELECT EMAIL
FROM TEMP_SOL
GROUP BY EMAIL
HAVING COUNT(*) > 1
</cfquery>

循环遍历dupEmail和

  1. 选择不必删除的用户名。
  2. 选择/删除不等于具有相同emailid的上述用户名的用户名。

    <cfloop query="dupEmail">
       <cfquery name="UserToRetain" datasource="XXX">
           SELECT USERNAME FROM TEMP_SOL
           WHERE EMAIL = '#dupEmail.Email#'
           ORDER BY START_DATE DESC NULLS LAST, ROWNUM DESC
           LIMIT 1 
      </cfquery>
    
      <cfquery name="DeleteUsers" datasource="XXX">
             SELECT * FROM TEMP_SOL
             WHERE USERNAME <> '#UserToRetain.USERNAME#' AND EMAIL='#dupEmail.Email#'
      </cfquery>
    
    </cfloop>
    
  3. 注意:上面的代码尚未经过测试,查询可能无法在mysql上运行。