Mysql-handling-duplicates
MySQL-重複の処理
一般に、テーブルまたは結果セットには重複レコードが含まれることがあります。 ほとんどの場合許可されていますが、重複レコードの停止が必要になる場合があります。 重複レコードを識別し、それらをテーブルから削除する必要があります。 この章では、テーブル内の重複レコードの発生を防ぐ方法と、既存の重複レコードを削除する方法について説明します。
テーブル内での重複の防止
適切なフィールドを持つテーブルで PRIMARY KEY または UNIQUE インデックスを使用して、重複レコードを停止できます。
例を見てみましょう–次の表には、そのようなインデックスや主キーが含まれていないため、 first_name と last_name の重複レコードが許可されます。
CREATE TABLE person_tbl (
first_name CHAR(20),
last_name CHAR(20),
sex CHAR(10)
);
同じ姓名の値を持つ複数のレコードがこのテーブルに作成されないようにするには、 PRIMARY KEY をその定義に追加します。 これを行うと、 PRIMARY KEY では NULL 値が許可されないため、インデックス付き列を NOT NULL として宣言する必要もあります-
CREATE TABLE person_tbl (
first_name CHAR(20) NOT NULL,
last_name CHAR(20) NOT NULL,
sex CHAR(10),
PRIMARY KEY (last_name, first_name)
);
テーブルに一意のインデックスが存在すると、通常、インデックスを定義する列の既存のレコードを複製するテーブルにレコードを挿入すると、エラーが発生します。
*INSERT* コマンドではなく、 *INSERT IGNORE* コマンドを使用します。 レコードが既存のレコードを複製しない場合、MySQLは通常どおりレコードを挿入します。 レコードが重複している場合、 *IGNORE* キーワードは、エラーを生成せずにサイレントに破棄するようMySQLに指示します。
次の例ではエラーは発生せず、同時に重複レコードも挿入されません。
mysql> INSERT IGNORE INTO person_tbl (last_name, first_name)
-> VALUES( 'Jay', 'Thomas');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT IGNORE INTO person_tbl (last_name, first_name)
-> VALUES( 'Jay', 'Thomas');
Query OK, 0 rows affected (0.00 sec)
INSERTコマンドではなく、 REPLACE コマンドを使用します。 レコードが新しい場合は、INSERTと同様に挿入されます。 重複している場合、新しいレコードが古いレコードを置き換えます。
mysql> REPLACE INTO person_tbl (last_name, first_name)
-> VALUES( 'Ajay', 'Kumar');
Query OK, 1 row affected (0.00 sec)
mysql> REPLACE INTO person_tbl (last_name, first_name)
-> VALUES( 'Ajay', 'Kumar');
Query OK, 2 rows affected (0.00 sec)
INSERT IGNOREおよびREPLACEコマンドは、実行する複製処理動作に従って選択する必要があります。 INSERT IGNOREコマンドは、複製されたレコードの最初のセットを保持し、残りを破棄します。 REPLACEコマンドは、重複の最後のセットを保持し、以前の重複を消去します。
一意性を強制する別の方法は、PRIMARY KEYではなく UNIQUE インデックスをテーブルに追加することです。
CREATE TABLE person_tbl (
first_name CHAR(20) NOT NULL,
last_name CHAR(20) NOT NULL,
sex CHAR(10)
UNIQUE (last_name, first_name)
);
重複のカウントと特定
以下は、テーブル内のfirst_nameとlast_nameを持つ重複レコードをカウントするクエリです。
mysql> SELECT COUNT(*) as repetitions, last_name, first_name
-> FROM person_tbl
-> GROUP BY last_name, first_name
-> HAVING repetitions > 1;
このクエリは、person_tblテーブル内のすべての重複レコードのリストを返します。 一般に、重複する値のセットを識別するには、以下の手順を実行します。
- 重複する可能性のある値が含まれている列を判別します。
- 列選択リストにそれらの列を* COUNT(*)*とともにリストします。
- GROUP BY 句の列もリストします。
- グループカウントを1より大きくする必要があるため、一意の値を削除する HAVING 句を追加します。
クエリ結果から重複を排除する
SELECTステートメントと一緒に DISTINCT コマンドを使用して、テーブルで使用可能な一意のレコードを見つけることができます。
mysql> SELECT DISTINCT last_name, first_name
-> FROM person_tbl
-> ORDER BY last_name;
DISTINCTコマンドの代わりに、選択する列に名前を付けるGROUP BY句を追加します。 これには、重複を削除し、指定された列の値の一意の組み合わせのみを選択するという効果があります。
mysql> SELECT last_name, first_name
-> FROM person_tbl
-> GROUP BY (last_name, first_name);
テーブル置換を使用した重複の削除
テーブルに重複するレコードがあり、そのテーブルからすべての重複するレコードを削除する場合は、次の手順に従います。
mysql> CREATE TABLE tmp SELECT last_name, first_name, sex
-> FROM person_tbl;
-> GROUP BY (last_name, first_name);
mysql> DROP TABLE person_tbl;
mysql> ALTER TABLE tmp RENAME TO person_tbl;
テーブルから重複レコードを削除する簡単な方法は、そのテーブルにINDEXまたはPRIMARY KEYを追加することです。 このテーブルが既に利用可能な場合でも、この手法を使用して重複レコードを削除でき、将来的にも安全です。
mysql> ALTER IGNORE TABLE person_tbl
-> ADD PRIMARY KEY (last_name, first_name);