如何在2列而不是1列中找到重复

我有一个 MySQL 数据库表,其中有两列引起了我的兴趣。单独地,它们可以各自有一个副本,但是它们不应该有两个具有相同价值的副本。

stone_id可以有重复,只要每个 upsharge标题是不同的,并在相反。但是举例来说,stone_id = 412和 upcharge_title = “蓝宝石”这种组合应该只出现一次。

没关系:

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

108800 次浏览

您应该在这两个字段之间设置一个复合键。这将需要为每一行使用惟一的 stone _ id 和 upcharge _ title。

至于找到现有的副本,请尝试这样做:

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。)

这篇 SO 文章帮助了我,但我也想知道如何删除并保留其中一行... 这里有一个 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`);

这有效地添加了唯一约束,这意味着您将永远不会有重复记录,IGNORE 将删除现有的重复记录。

你可以在这里阅读更多关于额忽略这里: http://mediakey.dk/~cc/mysql-remove-duplicate-entries/

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

它在 MySQL > 5.5和 InnoDB 表上失败,在 Percona 也失败,因为 他们的 InnoDB 快速索引创建功能[ http://bugs.mysql.com/bug.php?id=40344]。在这种情况下 首先运行 set session old_alter_table=1,然后运行上面的命令 没问题的

更新-ALTER IGNORE在5.7中删除

来自 医生

从 MySQL 5.6.17开始,不推荐使用 IGNORE 子句及其使用 在 MySQL 5.7中移除了 IGNORE。

其中一个 MySQL 开发人员给出了 两个选择:

  • 按唯一字段分组并删除,如上所示
  • 创建一个新表,添加一个唯一的索引,使用 INSERT IGNORE,例如:
CREATE TABLE duplicate_row_table LIKE regular_row_table;
ALTER TABLE duplicate_row_table ADD UNIQUE INDEX (id, another_id);
INSERT IGNORE INTO duplicate_row_table SELECT * FROM regular_row_table;
DROP TABLE regular_row_table;
RENAME TABLE duplicate_row_table TO regular_row_table;

但是根据桌子的大小,这可能不太实际

这就是我的工作(忽略空白)。两个不同的电子邮件专栏:

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