【MySQL】UPPER()・LOWER()で大文字と小文字を区別しないDISTINCTを実現する方法
MySQLで大文字・小文字を区別しないDISTINCTを実現する方法
MySQLのDISTINCT句は、デフォルトでは大文字と小文字を区別して比較を行います。そのため、「John@gmail.com」と「john@gmail.com」のような値は別々のデータとして扱われてしまいます。大文字と小文字を区別せずに重複を除外したい場合は、UPPER()関数またはLOWER()関数を組み合わせて使うのが定番の手法です。
方法1:UPPER()関数を使う(大文字に統一)
カラムの値をすべて大文字に変換した上でDISTINCTを適用します。構文は以下のとおりです。
SELECT DISTINCT UPPER(yourColumnName) FROM yourTableName;
方法2:LOWER()関数を使う(小文字に統一)
カラムの値をすべて小文字に変換した上でDISTINCTを適用します。構文は以下のとおりです。
SELECT DISTINCT LOWER(yourColumnName) FROM yourTableName;
検証用テーブルの作成
それでは、実際に動作を確認してみましょう。まずはサンプルテーブルを作成します。テーブル作成クエリは以下のとおりです。
mysql> create table CaseInsensitiveDistinctDemo
-> (
-> Id int NOT NULL AUTO_INCREMENT,
-> UserEmailId varchar(30),
-> UserPassword varchar(10),
-> PRIMARY KEY(Id)
-> );
Query OK, 0 rows affected (0.64 sec)
テストデータの挿入
続いて、INSERTコマンドでレコードを挿入します。ここでは、意図的に大文字・小文字の異なる同一メールアドレスを登録している点に注目してください。
mysql> insert into CaseInsensitiveDistinctDemo(UserEmailId,UserPassword) values('John@gmail.com','john123');
Query OK, 1 row affected (0.15 sec)
mysql> insert into CaseInsensitiveDistinctDemo(UserEmailId,UserPassword) values('john@gmail.com','654321');
Query OK, 1 row affected (0.43 sec)
mysql> insert into CaseInsensitiveDistinctDemo(UserEmailId,UserPassword) values('Mike@gmail.com','999999');
Query OK, 1 row affected (0.14 sec)
mysql> insert into CaseInsensitiveDistinctDemo(UserEmailId,UserPassword) values('mike@gmail.com','334556');
Query OK, 1 row affected (0.16 sec)
mysql> insert into CaseInsensitiveDistinctDemo(UserEmailId,UserPassword) values('Carol@gmail.com','1010101');
Query OK, 1 row affected (0.13 sec)
mysql> insert into CaseInsensitiveDistinctDemo(UserEmailId,UserPassword) values('Larry@gmail.com','12345678');
Query OK, 1 row affected (0.20 sec)登録済みデータの全件表示
SELECT文ですべてのレコードを表示して確認します。
mysql> select *from CaseInsensitiveDistinctDemo;
実行結果は以下のとおりです。
+----+-----------------+--------------+
| Id | UserEmailId | UserPassword |
+----+-----------------+--------------+
| 1 | John@gmail.com | john123 |
| 2 | john@gmail.com | 654321 |
| 3 | Mike@gmail.com | 999999 |
| 4 | mike@gmail.com | 334556 |
| 5 | Carol@gmail.com | 1010101 |
| 6 | Larry@gmail.com | 12345678 |
+----+-----------------+--------------+
6 rows in set (0.00 sec)
ご覧のとおり、「John@gmail.com」と「john@gmail.com」、「Mike@gmail.com」と「mike@gmail.com」がそれぞれ別の行として登録されています。この状態で単純にDISTINCTを使っても、結果は6件のまま変わりません。
大文字・小文字を区別しないDISTINCTクエリの実行
それでは、大文字・小文字を無視した重複排除を実行してみましょう。
ケース1:UPPER()を使用する場合
mysql> select distinct upper(UserEmailId) from CaseInsensitiveDistinctDemo;
実行結果:
+--------------------+
| upper(UserEmailId) |
+--------------------+
| JOHN@GMAIL.COM |
| MIKE@GMAIL.COM |
| CAROL@GMAIL.COM |
| LARRY@GMAIL.COM |
+--------------------+
4 rows in set (0.06 sec)
ケース2:LOWER()を使用する場合
mysql> select distinct lower(UserEmailId) from CaseInsensitiveDistinctDemo;
実行結果:
+--------------------+
| lower(UserEmailId) |
+--------------------+
| john@gmail.com |
| mike@gmail.com |
| carol@gmail.com |
| larry@gmail.com |
+--------------------+
4 rows in set (0.00 sec)
まとめ:実務での活用ポイント
どちらのケースでも、元の6件から大文字・小文字の違いを吸収した4件へ絞り込むことができました。特にメールアドレスのように大文字・小文字を同一視すべきデータを扱う際には、UPPER()やLOWER()を組み合わせたDISTINCTが非常に有効です。
なお、大量データを扱う場合は、関数を適用したカラムにはインデックスが効かなくなりクエリが遅くなる可能性がある点に注意しましょう。そのようなケースでは、生成カラム(Generated Column)に関数結果を格納してインデックスを作成するか、大文字・小文字を区別しない照合順序(ci系collation)の活用を検討するとよいでしょう。
-
MySQLで特定の項目ごとの件数を取得する方法(COUNTとGROUP BYの使い方)
MySQLでリスト内の特定の項目がそれぞれ何件ずつ存在するかを調べたい場合は、COUNT()関数とGROUP BY句を組み合わせるのが基本です。この記事では、実際にサンプルテーブルを作成し、特定の条件に一致する項目ごとの出現回数を集計する手順をわかりやすく解説します。 1. サンプルテーブルを作成する まずは、名前を格納するシンプルなテーブルを作成します。 mysql> create table DemoTable1854 ( Name varchar(20) &nb
-
MySQLで重複しない日付(個別の値)を表示する方法
MySQLでは、datetime型のカラムから「日付のみ」を基準に重複を排除してデータを取得したいケースがよくあります。例えば、同じ日に複数の注文や出荷記録がある場合、日付単位で1件だけ取り出したいときなどです。本記事では、GROUP BYとDATE()関数を組み合わせて、重複しない日付ごとのレコードを表示する方法を解説します。 1. サンプルテーブルを作成する まず、動作確認用のテーブルを作成しましょう。ここでは、出荷日時(ShippingDate)と顧客名(CustomerName)を持つテーブルを定義します。 mysql> create table DemoTable1996 (