Mysql 如何在2列而不是1列中查找重复项

Mysql 如何在2列而不是1列中查找重复项,mysql,duplicates,Mysql,Duplicates,我有一个MySQL数据库表,其中有两列我感兴趣。单独而言,它们可以各有一个副本,但它们不应同时拥有两个具有相同值的副本 stone_id可以有重复项,只要每个追加收费标题不同,反之亦然。但比如说stone_id=412和upcharge_title=sapphire,这种组合只应该出现一次 这没关系: stone_id = 412 upcharge_title = "sapphire" stone_id = 412 upcharge_title = "ruby" 这不好: stone_id =

我有一个MySQL数据库表,其中有两列我感兴趣。单独而言,它们可以各有一个副本,但它们不应同时拥有两个具有相同值的副本

stone_id可以有重复项,只要每个追加收费标题不同,反之亦然。但比如说stone_id=412和upcharge_title=sapphire,这种组合只应该出现一次

这没关系:

stone_id = 412 upcharge_title = "sapphire"
stone_id = 412 upcharge_title = "ruby"
这不好:

stone_id = 412 upcharge_title = "sapphire"
stone_id = 412 upcharge_title = "sapphire"
是否存在在两个字段中都会找到重复项的查询?如果可能的话,有没有办法将我的数据库设置为不允许这样做


我使用的是MySQL版本4.1.22,您应该在这两个字段之间设置一个复合键。这将要求每行具有唯一的stone_id和upcharge_标题

要查找现有的重复项,请尝试以下方法:

select   stone_id,
         upcharge_title,
         count(*)
from     your_table
group by stone_id,
         upcharge_title
having   count(*) > 1

要查找重复项,请执行以下操作:

select stone_id, upcharge_title from tablename group by stone_id, upcharge_title having count(*)>1

要约束以避免将来出现这种情况,请在这两个字段上创建一个复合唯一键。

您可以找到类似的重复项

Select
    stone_id, upcharge_title, count(*)
from 
    particulartable
group by 
    stone_id, upcharge_title
having 
    count(*) > 1

顺便说一句,表上的复合唯一约束将首先防止这种情况发生

ALTER TABLE table
    ADD UNIQUE(stone_id, charge_title)

这是有效的T-SQL。不太清楚MySQL。

这篇文章对我有所帮助,但我也想知道如何删除和保留其中一行。。。这里有一个PHP解决方案,可以删除重复的行并保留一行。在我的例子中,只有2列,它位于清除重复类别关联的函数中

$dupes = $db->query('select *, count(*) as NUM_DUPES from PRODUCT_CATEGORY_PRODUCT group by fkPRODUCT_CATEGORY_ID, fkPRODUCT_ID having count(*) > 1');
if (!is_array($dupes))
    return true;
foreach ($dupes as $dupe) {
    $db->query('delete from PRODUCT_CATEGORY_PRODUCT where fkPRODUCT_ID = ' . $dupe['fkPRODUCT_ID'] . ' and fkPRODUCT_CATEGORY_ID = ' . $dupe['fkPRODUCT_CATEGORY_ID'] . ' limit ' . ($dupe['NUM_DUPES'] - 1);
}
限制NUM_DUPES-1是保留单行的原因


谢谢大家

我发现使用ALTER IGNORE添加一个unqiue索引很有帮助,它可以删除重复项并强制执行唯一记录,这听起来像是您想要做的。所以语法应该是:

ALTER IGNORE TABLE `table` ADD UNIQUE INDEX(`id`, `another_id`, `one_more_id`);
这有效地添加了唯一约束,这意味着您将永远不会有重复的记录,而忽略将删除现有的重复记录

您可以在此处阅读有关eh ALTER IGNORE的更多信息:

更新:@Inquisitive通知我,在MySql>5.5的版本中,这可能会失败:

它在MySQL>5.5和InnoDB表上失败,在Percona中失败是因为 他们的InnoDB快速索引创建功能[.在本例中 首先运行set session old_alter_table=1,然后运行上述命令 行吗

更新-在5.7中删除了ALTER IGNORE

从MySQL 5.6.17开始,IGNORE子句已被弃用,它的使用 生成警告。忽略在MySQL 5.7中被删除

MySQL开发人员的一个建议是:

按唯一字段分组并如上所示删除 创建新表,添加唯一索引,使用INSERT IGNORE,例如:
但是,根据您表格的大小,这可能不太实际

忽略null和blank对我来说很有效。两个不同的电子邮件列:

SELECT * 
FROM   members 
WHERE  email IN (SELECT soemail 
                 FROM   members 
                 WHERE  NOT Isnull(soemail) 
                        AND soemail <> ''); 

非常感谢,你能告诉我如何删除除一个副本以外的所有副本吗?以及如何在phpmyadmin中设置compisite密钥。谢谢!!!我认为这是可行的,但在我先删除副本之前它不会让我这样做。谢谢。谢谢,这确实选择了副本。你能告诉我如何删除副本,但在当然谢谢!!一种方法是获取所有不同的数据并重新创建表。@John Isaacks:如果没有其他字段可以区分它们,即所有字段都是重复的,那么您必须删除两行并重新创建一行。一种方法是将重复项复制到表的副本中,从原始字段中删除它们,&从副本中重新插入不同的行。这在postgres 8.1上不起作用,有人能帮我一下吗?非常感谢,您分组的顺序重要吗?ALTER IGNORE TABLE TABLE ADD UNIQUE INDEX INDEX\u namestone\u id,charge\u title将删除重复行,只留下一对唯一的行。是的,但至少下次您知道。我有同样的问题,并认为与其他人分享是件好事。我只是取笑它晚了3年。真的很高兴你分享了。因此加1。我想这会任意删除其中一个重复项,因此确保每行之间没有可能有用的不同数据。即使晚了2年,答案也为+1。我意外地发现ally删除了一个复合密钥,这是一个救命稻草。谢谢。我尝试了一些重复查找技术,但没有一种这么简单和快速。谢谢你分享这个方法。
SELECT * 
FROM   members 
WHERE  email IN (SELECT soemail 
                 FROM   members 
                 WHERE  NOT Isnull(soemail) 
                        AND soemail <> '');