MySQLでGROUP BYとHAVINGを使って重複行を検出する方法
MySQLでテーブル内の重複行を見つけるには、GROUP BY句とHAVING句を組み合わせるのが最も基本的かつ効果的な方法です。この記事では、サンプルテーブルを作成し、実際に重複データを検出する手順をわかりやすく解説します。
1. サンプルテーブルの作成
まず、出荷日(ShippingDate)と顧客の国名(CustomerCountryName)を持つテーブルを作成します。
mysql> create table DemoTable1494
-> (
-> ShippingDate datetime,
-> CustomerCountryName varchar(20)
-> );
Query OK, 0 rows affected (0.63 sec)
2. テストデータの挿入
次に、INSERTコマンドを使っていくつかのレコードを挿入します。意図的に同じ日付・同じ国名の組み合わせを含めています。
mysql> insert into DemoTable1494 values('2018-09-10 12:34:50','US');
Query OK, 1 row affected (0.11 sec)
mysql> insert into DemoTable1494 values('2019-09-10 12:34:50','AUS');
Query OK, 1 row affected (0.65 sec)
mysql> insert into DemoTable1494 values('2018-09-10 11:00:00','US');
Query OK, 1 row affected (0.13 sec)
mysql> insert into DemoTable1494 values('2017-12-31 01:10:40','UK');
Query OK, 1 row affected (0.19 sec)
mysql> insert into DemoTable1494 values('2019-09-10 05:00:50','AUS');
Query OK, 1 row affected (0.49 sec)3. 挿入したレコードの確認
SELECT文ですべてのレコードを表示してみましょう。
mysql> select * from DemoTable1494;
実行結果は以下の通りです。
+---------------------+---------------------+
| ShippingDate | CustomerCountryName |
+---------------------+---------------------+
| 2018-09-10 12:34:50 | US |
| 2019-09-10 12:34:50 | AUS |
| 2018-09-10 11:00:00 | US |
| 2017-12-31 01:10:40 | UK |
| 2019-09-10 05:00:50 | AUS |
+---------------------+---------------------+
5 rows in set (0.00 sec)
4. 重複行を検出するクエリ
ここが本題です。date()関数で日時から日付部分だけを取り出し、それと国名を組み合わせてグループ化することで、「同じ日・同じ国」の組み合わせを重複として検出できます。
mysql> select ShippingDate,CustomerCountryName,count(*) as c
-> from DemoTable1494
-> group by date(ShippingDate),CustomerCountryName
-> having c >=2
-> order by c;
実行すると、以下のように重複している組み合わせのみが抽出されます。
+---------------------+---------------------+---+
| ShippingDate | CustomerCountryName | c |
+---------------------+---------------------+---+
| 2018-09-10 12:34:50 | US | 2 |
| 2019-09-10 12:34:50 | AUS | 2 |
+---------------------+---------------------+---+
2 rows in set (0.00 sec)
クエリのポイント解説
- GROUP BY date(ShippingDate), CustomerCountryName:datetime型のままだと時刻まで含めて比較されるため、
date()関数で日付部分に丸めてグループ化しています。これにより「同日の同一国」を重複として扱えます。 - HAVING c >= 2:
WHERE句は集計前の行に対する条件ですが、集計後の件数で絞り込む場合はHAVING句を使う必要があります。ここでは2件以上存在するグループのみを抽出しています。 - count(*) as c:各グループの行数をカウントし、エイリアス「c」として表示しています。ORDER BY c を付けることで、重複数の少ない順に並べて見やすくしています。
この手法は、複数カラムの組み合わせによる重複チェック全般に応用できます。たとえばユーザーテーブルでの「メールアドレス+登録日」の重複確認や、ログテーブルの異常検知などにも活用できるので、ぜひ覚えておきましょう。
-
MySQLで重複行を除外して1行だけ取得する方法(DISTINCTの使い方)
MySQLで重複行から1行のみを返すには?MySQLのテーブルに同じ値を持つ重複行が存在する場合、DISTINCTキーワードを使うことで、重複を排除した一意な行だけを取得できます。この記事では、実際にテーブルを作成し、データを挿入したうえで、DISTINCTによる重複除去の手順を解説します。1. テーブルを作成するまず、サンプル用のテーブルを作成します。mysql> create table DemoTable1998 ( Name varchar(20) ); Query OK, 0 rows affected (0.61 sec)2. レコードを挿入するINSERTコマンドを
-
MySQLの複合インデックス(コンポジットインデックス)とは?特徴と作成方法を解説
複合インデックス(コンポジットインデックス)とは、複数のカラムに対して設定されるインデックスのことです。マルチカラムインデックスとも呼ばれます。単一カラムのインデックスでは対応しきれない検索条件を効率化できるため、実務でも頻繁に活用される重要な機能です。 複合インデックスの主な特徴 複合インデックスには、以下のような特徴があります。 MySQLでは、最大16個のカラムで構成される複合インデックスを作成できます。 クエリオプティマイザは、インデックスに含まれるすべてのカラムが検索条件で使われるクエリに対して、複合インデックスを利用します。 さらに、先頭の1カラムだけ、先頭の2カラムなど、部分的