我看到很多方法可以找到重复的记录并删除它们,但我找不到我要找的那个,即根据某些条件删除它们。
下面从另一篇文章中获取的第一个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.两个问题:
如何修改代码以处理方案?我想保留#4和#6的记录,因为4比2更新,6比6更新。
4 user4 test@test.com 11/02/2014
6 user6 me@mydomain.com
答案 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和
选择/删除不等于具有相同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>
注意:上面的代码尚未经过测试,查询可能无法在mysql上运行。