MySQL で重複レコードを見つけて削除する方法

MySQL で重複レコードを見つけて削除する方法

みなさんこんにちは。私は技術の話ばかりして髪を切らない先生のトニーです。何らかの歴史的な理由や誤操作により、データ テーブルに重複レコードが存在する場合があります。今日は、MySQL テーブルで重複データを検索する方法と、これらの重複レコードを削除する方法について説明します。

サンプルテーブルを作成する

まず、サンプル テーブル people を作成し、データを生成します。

存在する場合はテーブルを削除します。
テーブルを作成する人(
 id int auto_increment 主キー、
 名前varchar(50)がnullではない、
 電子メールvarchar(100)がnullでない
);

人々に挿入(名前、メールアドレス)
値('张三'、'[email protected]')、
  (「Li Si」、「[email protected]」)、
  (「王武」、「[email protected]」)、
  ('李斯', '[email protected]'),
  (「王武」、「[email protected]」)、
  ('Wang Wu'、'[email protected]');

人から*を選択します。
ID|名前|メール|
--|------|-----------------|
 1|張三|[email protected]|
 2|李思|[email protected] |
 3|王武|[email protected] |
 4|リシ|[email protected] |
 5|王武|[email protected] |
 6|王武|[email protected] |

このうち、2 と 4 のメール フィールドに重複データがあり、3、5、6 の名前とメール フィールドに重複データがあります。

この時点で、電子メールの一意の制約を作成しようとすると、エラーが返されます。

テーブル people を変更し、制約 uk_people_email に一意のキー (email) を追加します。
エラー 1062 (23000): キー「people.uk_people_email」のエントリ「[email protected]」が重複しています

当然のことながら、一意の制約を作成するには、電子メール フィールド内の重複レコードを見つけて削除する必要があります。

単一のフィールドで重複データを検索する

重複するメール データを検索する場合は、このフィールドに基づいてグループ化してカウントし、1 行を超えるグループを返すことができます。

メールを選択し、count(email)
人々から
メールでグループ化
count(email) > 1 であること
メール |count(メール)|
---------------|-------------|
[email protected] | 2|
[email protected]| 3|

クエリ結果には、重複する電子メール アドレスが 2 つあることが示されています。完全な重複データを表示する場合は、サブクエリまたは結合クエリを使用できます。

*を選択
人々から
メールアドレス(
  メールを選択
  人々から
  メールでグループ化
  count(email) > 1)を持つ
電子メールで注文する;
ID|名前|メール|
--|------|--------------|
 2|李思|[email protected] |
 4|リシ|[email protected] |
 3|王武|[email protected]|
 5|王武|[email protected]|
 6|王武|[email protected]|

p.*を選択
人々から
参加する (
 メールを選択
 人々から
 メールでグループ化
 count(email) > 1 を持つ
) d は p.email 上にあります = d.email
電子メールで注文する;
ID|名前|メール|
--|------|--------------|
 2|李思|[email protected] |
 4|リシ|[email protected] |
 3|王武|[email protected]|
 5|王武|[email protected]|
 6|王武|[email protected]|

重複レコードを見つける別の方法は、自己結合クエリと distinct 演算子を直接使用することです。次に例を示します。

異なる p を選択*
人々から
p.email = d.email で人々 d に参加
ここで、p.id <> d.id
メールで注文してください。
ID|名前|メール|
--|------|--------------|
 4|リシ|[email protected] |
 2|李思|[email protected] |
 6|王武|[email protected]|
 5|王武|[email protected]|
 3|王武|[email protected]|

注意: distinct は省略できません。省略すると、一部のデータ (3、5、6) が複数回返されます。

複数のフィールドで重複データを検索する

名前とメールのフィールドが重複しているデータを検索する場合、実装は同様です。

*を選択
人々から
(名前、メールアドレス) が (
  名前、メールアドレスを選択
  人々から
  名前、メールアドレスでグループ化
  count(1) > 1)を持つ
電子メールで注文する;
ID|名前|メール|
--|------|--------------|
 3|王武|[email protected]|
 5|王武|[email protected]|
 6|王武|[email protected]|

異なる p を選択*
人々から
p.name = d.name および p.email = d.email で人 d に参加
ここで、p.id <> d.id
電子メールで注文する;
ID|名前|メール|
--|------|--------------|
 6|王武|[email protected]|
 5|王武|[email protected]|
 3|王武|[email protected]|

重複データは名前と電子メールの両方が同じ場合にのみ発生するため、2 と 4 は重複レコードではありません。

重複排除

重複データを見つけたら、それをどうやって削除するかという問題を解決する必要があります。通常は、レコードの 1 つを保持する必要があります。

DELETE FROM を使用して重複データを削除する

重複する電子メール レコードを削除して 1 つだけ残したい場合は、DELETE FROM ステートメントを使用してこれを実現できます。

削除p
人々から
p.email = d.email かつ p.id < d.id で人々 d を結合します。

delete ステートメントは、接続を使用して削除するレコードを検索します。上記の例では、重複データ内の最大 ID に対応するデータ行が保持されます。 people テーブルを再度クエリします。

人から*を選択します。
ID|名前|メール|
--|------|-----------------|
 1|張三|[email protected]|
 4|リシ|[email protected] |
 6|王武|[email protected] |

考えてみてください。重複データの中で ID が最小のデータを保持したい場合、どうすればよいでしょうか?

サブクエリを使用して重複データを削除する

サブクエリを使用して、保持する必要があるデータを検索し、残りを削除できます。

消去
人々から
IDが(
  最大(ID)を選択
  人々から
  メールでグループ化
  );

上記のステートメントを実行する前に、people テーブルを再作成し、テスト データを生成することを忘れないでください。

中間テーブルを通じて重複データを削除する

重複レコードの削除は、中間テーブルを使用して実行することもできます。次に例を示します。

-- 中間テーブルを作成します。create table people_temp like people;

-- 保持する必要があるデータ行をコピーし、people_temp (id、name、email) に挿入します。
ID、名前、メールアドレスを選択
人々から
idが(
  最大(ID)を選択
  人々から
  メールでグループ化
  );

--元のテーブルを削除します。drop table people;

-- 中間テーブルの名前を元のテーブルに変更します。alter table people_temp rename to people;

上記のステートメントを実行する前に、people テーブルを再作成し、テスト データを生成することを忘れないでください。

この方法で注意する必要があることの 1 つは、create table ... like ステートメントでは元のテーブルの外部キー制約がコピーされないため、手動で追加する必要があることです。

ウィンドウ関数を使用して重複データを削除する

ROW_NUMBER() は、データをグループ化し、各データに一意の番号を割り当てるために使用できる MySQL 8.0 の新しいウィンドウ関数です。例えば:

ID、名前、メールアドレスを選択 
  row_number() を (電子メールによるパーティション、ID による順序) で row_num として計算します。 
人々から;
ID|名前|メール|行番号|
--|------|-----------------|-------|
 2|李思|[email protected] | 1|
 4|リシ|[email protected] | 2|
 3|王武|[email protected] | 1|
 5|王武|[email protected] | 2|
 6|王武|[email protected] | 3|
 1|張さん|[email protected]| 1|

上記のステートメントは、データを電子メールでグループ化し (電子メールでパーティション)、ID で並べ替え (ID で順序付け)、各グループのデータに番号を割り当てます。番号が 1 より大きい場合は、重複データがあることを意味します。

📝ROW_NUMBER() に加えて、RANK() または DENSE_RANK() 関数でも上記の機能を実現できます。ウィンドウ関数の紹介と使用例については、こちらの記事を参照してください。

クエリ結果に基づいて、重複レコードを削除できます。

消去
人々から
idが(
 IDを選択
 から (
  IDを選択、
    row_number() を (電子メールによるパーティション、ID による降順) で row_num として計算します。 
  人から
 ここで、行番号 > 1 です);

上記のステートメントを実行する前に、people テーブルを再作成し、テスト データを生成することを忘れないでください。

複数のフィールドに基づいてデータの重複を排除する方法は、単一のフィールドの場合と非常に似ています。 ぜひご自身で試していただき、ディスカッションのためにメッセージを残してください。

要約する

この記事では、GROUP BY、サブクエリ、または結合クエリを使用して単一のフィールドまたは複数のフィールドで重複データを検索する方法、および DELETE FROM ステートメント、サブクエリ、中間テーブル、およびウィンドウ関数を使用して重複データを削除する方法など、MySQL で重複レコードを検索して削除する方法について説明します。 MySQL 重複レコードの検索と削除の詳細については、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。 今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • MySQL にテーブルが存在するかどうかを確認し、それを一括で削除する方法
  • MySQL でデータを削除してもテーブル ファイルのサイズが変更されないのはなぜですか?
  • MySQL でテーブルを削除する 3 つの方法 (要約)
  • MySQL で大量のデータ (数千万) を素早く削除するためのいくつかの実用的なソリューションの詳細な説明
  • MySQLサービスを削除する具体的な方法
  • MySQL の重複データの処理方法 (防止と削除)
  • MySQL データベース操作 (作成、選択、削除)
  • Windows で削除された MySQL 8.0.17 のルート アカウントとパスワードを回復する方法
  • Linux で MySQL 8.0 サービスを完全に削除する方法
  • MySQL テーブル削除操作の実装 (delete、truncate、drop の違い)
  • MySQL で削除されたレコードが有効にならない理由のトラブルシューティング

<<:  jsはウォーターフォールフローのボトムアウトによるデータの動的ロードを実現します

>>:  Alibaba Cloud に Docker をインストールする際の問題と解決策

推薦する

Docker ロード後にイメージ名が none になる問題の解決方法

最近、docker load -i コマンドを使用してイメージ パッケージを圧縮した後、イメージ名と...

デザインにおいて無視できないインタラクティブデザインにおける製品状態の分析

製品デザインのプロセスにおいて、デザイナーは常に写真を非常に美しくすることを好みます。仮想ページのコ...

リモートホスト上でスクリプトや命令を実行する Zabbix の詳細な説明

シナリオ要件1. zabbix_server Web インターフェースのスクリプト機能を使用すると、...

Vueはデータを初期状態にリセットします

場合によっては、データ内のデータを再利用する必要がありますが、データ内のデータはさまざまなフォーム、...

Docker クロスホストネットワークの実装 (手動)

1. Macvlan の紹介Macvlan が登場する前は、イーサネット カードに複数の IP ア...

Linux のよく使うコマンドの使い方を詳しく解説(第 2 回)———— テキストエディタのコマンド vi/vim

vi/vim の紹介どちらもマルチモード エディターです。違いは、vim が vi のアップグレー...

MySQL で特定の親行のすべての子行を見つけるソリューション

序文注: テストデータベースのバージョンはMySQL 8.0ですテーブルを作成し、ユーザー scot...

仮想マシンの複製に関するVirtual Boxチュートリアル図

VMに慣れた後、BOXに切り替えるのは少し異なります。たとえば、コピーネットワークカードを2枚使って...

JavaScript におけるイベント バブリング メカニズムの詳細な分析

バブリングとは何ですか? DOM イベント フローには、イベント キャプチャ ステージ、ターゲット ...

ネイティブ js が携帯電話のプルダウン更新を模倣

この記事では、携帯電話のプルダウンリフレッシュを模倣したjsの具体的なコードを参考までに共有します。...

CSS3 フリップカード番号サンプルコード

今日会社から課題をもらったのですが、効果図は以下のとおりです。 どのような効果を実現したいかは特に決...

MySQLスレーブライブラリの復元の実践記録

状況の説明:今日、MySQL データベースのスレーブ ノード ホストにログインしたところ、/var/...

FileZilla 425 FTP に接続できない (Alibaba クラウド サーバー) の解決策

Alibaba Cloud ServerがFTPに接続できないFileZilla 425 データ接続...

フロントエンドに必要なNginx設定の詳細な説明

Nginx (エンジン x) は、軽量で高性能な HTTP およびリバース プロキシ サーバーであり...

CSSを使用してファイルアップロードパターンを描画する

以下に示すように、あなたならどのようにそれを達成しますか: 通常、フォントアイコンを使用して中央にプ...