我有一个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版本
答案 0 :(得分:167)
您应该在两个字段之间设置复合键。这将需要每行一个独特的stone_id和upcharge_title。
就查找现有重复项而言,请尝试以下方法:
select stone_id,
upcharge_title,
count(*)
from your_table
group by stone_id,
upcharge_title
having count(*) > 1
答案 1 :(得分:32)
我发现使用“ALTER IGNORE”添加unqiue索引很有帮助,它可以删除重复项并强制执行您想要的独特记录。所以语法是:
ALTER IGNORE TABLE `table` ADD UNIQUE INDEX(`id`, `another_id`, `one_more_id`);
这有效地添加了唯一约束,这意味着您永远不会有重复记录,IGNORE会删除现有的重复记录。
您可以在此处阅读更多关于eh ALTER 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
来自docs
从MySQL 5.6.17开始,不推荐使用IGNORE子句及其使用 生成警告。在MySQL 5.7中删除了IGNORE。
其中一个MySQL开发者提供two alternatives:
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;
但是根据你桌子的大小,这可能不实用
答案 2 :(得分:6)
你可以找到像这样的重复...
Select
stone_id, upcharge_title, count(*)
from
particulartable
group by
stone_id, upcharge_title
having
count(*) > 1
答案 3 :(得分:4)
要查找重复项:
select stone_id, upcharge_title from tablename group by stone_id, upcharge_title having count(*)>1
要限制在将来避免这种情况,请在这两个字段上创建复合唯一键。
答案 4 :(得分:3)
顺便说一句,表上的复合唯一约束会阻止这种情况发生。
ALTER TABLE table
ADD UNIQUE(stone_id, charge_title)
(这是有效的T-SQL。不确定MySQL。)
答案 5 :(得分:0)
这篇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)是保留单行的原因......
感谢所有
答案 6 :(得分:0)
这对我有用(忽略空值和空白)。两个不同的电子邮件列:
SELECT *
FROM members
WHERE email IN (SELECT soemail
FROM members
WHERE NOT Isnull(soemail)
AND soemail <> '');