【问题标题】:How to find duplicates in 2 columns not 1如何在 2 列而不是 1 列中查找重复项
【发布时间】:2010-10-13 03:52:33
【问题描述】:

我有一个 MySQL 数据库表,其中包含我感兴趣的两列。单独地,他们每个人都可以有重复项,但他们永远不应该有两个具有相同值的重复项。

stone_id 可以有重复,只要每个upsharge 的标题不同,反之亦然。但是例如 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 版

【问题讨论】:

    标签: mysql duplicates


    【解决方案1】:

    您应该在两个字段之间设置一个复合键。这将要求每行都有一个唯一的 stone_id 和 upcharge_title。

    只要找到现有的重复项,试试这个:

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

    【讨论】:

    • 谢谢,确实选择了他们。你能告诉我如何删除重复项(但当然要留下一份)谢谢!!
    • 一种方法是获取所有不同的数据并重新创建表。
    • @John Isaacks:如果没有其他可以区分它们的字段(即所有字段都是重复的),那么您必须删除这两行并重新创建一个。一种方法是将重复项复制到表的副本中,从原始表中删除它们,然后从副本中重新插入不同的行。
    • 这在 postgres 8.1 上不起作用,有人可以帮帮我吗?
    • 非常感谢,您按分组的顺序重要吗?
    【解决方案2】:

    我发现使用“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 子句已被弃用,它的使用 生成警告。 IGNORE 在 MySQL 5.7 中被移除。

    其中一位 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;
    

    但根据您的桌子的大小,这可能不实用

    【讨论】:

    • 没错,但至少下次你知道。我有同样的问题,并认为与他人分享很好
    • 我只是在取笑它迟到了 3 年。真的很高兴你分享。因此加 1。
    • 我想这会任意删除其中一个重复项,因此请确保每行之间没有可能有助于了解或保留的不同数据。
    • 即使晚了 2 年也能得到答案+1。我不小心删除了一个复合键,这是一个救命稻草。谢谢
    • 我尝试了一些重复查找技术,但没有一个是这么简单和快速的。感谢您分享此方法。
    【解决方案3】:

    你可以找到这样的重复..

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

    【讨论】:

      【解决方案4】:

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

      ALTER TABLE table
          ADD UNIQUE(stone_id, charge_title)
      

      (这是有效的 T-SQL。不确定 MySQL。)

      【讨论】:

      • 我认为这行得通,但它不会让我这样做,直到我先删除重复项。谢谢。
      【解决方案5】:

      要查找重复项:

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

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

      【讨论】:

      • 非常感谢,您能告诉我如何删除除一个重复项之外的所有重复项。以及如何在 phpmyadmin 中设置一个 compisite 密钥。谢谢!!!
      【解决方案6】:

      这篇 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);
      }
      

      (limit NUM_DUPES - 1) 是保留单行的原因...

      谢谢大家

      【讨论】:

      • ALTER IGNORE TABLE table ADD UNIQUE INDEX index_name(stone_id, charge_title) 将删除重复的行,只留下一个唯一的对。
      【解决方案7】:

      这对我有用(忽略 null 和空白)。两个不同的电子邮件栏:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-05-23
        • 2014-09-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-29
        • 2013-02-21
        • 2013-11-17
        相关资源
        最近更新 更多