125

興味のある 2 つの列を持つ MySQL データベース テーブルがあります。個別に、それぞれが重複する可能性がありますが、同じ値を持つ両方の重複を持つことはできません。

stone_id各タイトルが異なる限り、重複する可能性がupshargeあり、逆の場合もあります。ただし、たとえばstone_id= 412 とupcharge_title= "sapphire" の組み合わせは 1 回だけにする必要があります。

これで結構です:

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 を使用しています

4

7 に答える 7

36

「ALTER IGNORE」を使用して一意のインデックスを追加すると、重複を削除し、やりたいように聞こえる一意のレコードを強制することが役立つことがわかりました。したがって、構文は次のようになります。

ALTER IGNORE TABLE `table` ADD UNIQUE INDEX(`id`, `another_id`, `one_more_id`);

これにより、一意の制約が効果的に追加され、レコードが重複することがなくなり、IGNORE によって既存の重複が削除されます。

ここで 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 IGNORE5.7 で削除

ドキュメントから

MySQL 5.6.17 の時点で、 IGNORE 句は廃止され、その使用は警告を生成します。IGNORE は MySQL 5.7 で削除されました。

MySQL開発者の1人が2つの選択肢を提供しています:

  • 上記のように、一意のフィールドでグループ化し、削除します
  • 新しいテーブルを作成し、一意のインデックスを追加し、使用します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;

ただし、テーブルのサイズによっては、これは実用的ではない場合があります

于 2012-06-14T22:44:46.260 に答える
1

このSOの投稿は私を助けましたが、私も行の1つを削除して保持する方法を知りたいと思っていました...重複した行を削除して1つを保持する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) は、単一の行を保持するものです...

皆さんありがとう

于 2010-08-19T21:34:46.363 に答える