如何在 MySQL 中删除具有几个相同值的行?
Posted
技术标签:
【中文标题】如何在 MySQL 中删除具有几个相同值的行?【英文标题】:How can I delete rows with a few identical values in MySQL? 【发布时间】:2015-02-20 13:20:39 【问题描述】:我有一个包含大约 11 个字段(列)的表,我知道有多个重复条目,但它们只在几个字段中重复。我想要做的是,如果两行或多行具有相同的小写ProviderName
和Address
,以及相同的StateID
,那么我想删除那些额外的行,只留下一份副本。我有类似的东西,但我不知道如何完成它。
SET SQL_SAFE_UPDATEs=0;
DELETE FROM providers
WHERE LCASE(ProviderName), LCASE(Address), StateID;
更新:
SET SQL_SAFE_UPDATES=0;
DELETE p1.*
FROM providers AS p1
JOIN providers AS p2
ON LCASE(p1.ProviderName) = LCASE(p2.ProviderName)
AND LCASE(p1.Address) = LCASE(p2.Address)
AND p1.Zip = p2.Zip
AND p1.StateID = p2.StateID
AND p1.ProviderId > p2.ProviderId
【问题讨论】:
【参考方案1】:此答案假定您有一个唯一的 id
字段,用于区分具有重复值的行。它将保留id
最低的行。
DELETE p1.*
FROM providers AS p1
JOIN providers AS p2
ON LCASE(p1.ProviderName) = LCASE(p2.ProviderName)
AND LCASE(p1.Address) = LCASE(p2.Address)
AND p1.StateID = p2.StateID
AND p1.id > p2.id
请注意,如果您的表格使用不区分大小写的排序规则,则无需调用LCASE
。
更有效的查询可能是:
DELETE p1.*
FROM providers AS p1
JOIN (SELECT LCASE(ProviderName) AS Name, LCASE(Address) AS Addr, StateID, MIN(id) AS id
FROM providers
GROUP BY Name, Addr, StateID
HAVING COUNT(*) > 1) AS p2
ON LCASE(p1.ProviderName) = p2.Name
AND LCASE(p1.Address) = p2.Addr
AND p1.StateID = p2.StateID
AND p1.id > p2.id
叉积要小得多,因为我们首先将所有具有相同值的提供者分组。此外,HAVING
子句过滤掉所有非重复项。
【讨论】:
从你的经验来看,你不介意看看我的question吗? 你能检查我更新的代码吗,实际上是你的,当我执行它时,我收到以下消息:Error Code: 1205. Lock wait timeout exceeded; try restarting transaction
。我每个人都有唯一的ProviderId
,当我选择使用您的代码时,请检查此屏幕截图:prntscr.com/67jer1
你的桌子有多大?这个查询不是很容易被索引,所以如果表很大的话会很慢。
@Barmar 我的表中有大约 900 万个条目。
如果您使用不区分大小写的排序规则,并且在您要比较的列上有一个复合索引,这会很有帮助。您不能为比较函数调用结果的查询编制索引。【参考方案2】:
要离开具有最高 id 的条目:
SET SQL_SAFE_UPDATES = 0;
DELETE n1 FROM provider n1, provider n2 WHERE n1.id < n2.id AND
LCASE(n1.ProviderName) = LCASE(n2.ProviderName) and LCASE(n1.Address) =
LCASE(n2.Address)
and n1.StateId = n2.StateId
【讨论】:
这会留下 ID 最高的条目,而不是最低的。以上是关于如何在 MySQL 中删除具有几个相同值的行?的主要内容,如果未能解决你的问题,请参考以下文章