MySQLのSELECT DISTINCTを複数カラムに適用する方法
MySQLでSELECT DISTINCTを複数カラムに使うには?
MySQLのSELECT DISTINCTは、通常1つのカラムの重複を排除するために使われますが、複数のカラムを組み合わせて重複行を除外したい場合には、サブクエリやGROUP BYを活用したテクニックが必要になります。
この記事では、具体的なサンプルテーブルを作成しながら、複数カラムに対して実質的にDISTINCTを実現する方法を解説します。
1. サンプルテーブルの作成
まず、講師(Instructor)、受講生(Student)、技術科目(TechnicalSubject)の情報を格納するテーブルを作成します。テーブル作成のクエリは以下のとおりです。
mysql> create table selectDistinctDemo
-> (
-> InstructorId int NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> StudentId int,
-> TechnicalSubject varchar(100)
-> );
Query OK, 0 rows affected (0.50 sec)
2. テストデータの挿入
次に、INSERT文を使っていくつかのレコードを挿入します。意図的に同じStudentIdを持つ複数のレコードを含めています。
mysql> insert into selectDistinctDemo(StudentId,TechnicalSubject) values(121,'Java'); Query OK, 1 row affected (0.15 sec) mysql> insert into selectDistinctDemo(StudentId,TechnicalSubject) values(121,'MongoDB'); Query OK, 1 row affected (0.16 sec) mysql> insert into selectDistinctDemo(StudentId,TechnicalSubject) values(121,'MySQL'); Query OK, 1 row affected (0.15 sec) mysql> insert into selectDistinctDemo(StudentId,TechnicalSubject) values(298,'Python'); Query OK, 1 row affected (0.11 sec) mysql> insert into selectDistinctDemo(StudentId,TechnicalSubject) values(298,'SQL Server'); Query OK, 1 row affected (0.15 sec) mysql> insert into selectDistinctDemo(StudentId,TechnicalSubject) values(397,'C#'); Query OK, 1 row affected (0.13 sec)
3. 全レコードの確認
SELECT文ですべてのレコードを表示してみましょう。
mysql> select *from selectDistinctDemo;
以下が出力結果です。
+--------------+-----------+------------------+ | InstructorId | StudentId | TechnicalSubject | +--------------+-----------+------------------+ | 1 | 121 | Java | | 2 | 121 | MongoDB | | 3 | 121 | MySQL | | 4 | 298 | Python | | 5 | 298 | SQL Server | | 6 | 397 | C# | +--------------+-----------+------------------+ 6 rows in set (0.00 sec)
ご覧のとおり、StudentId「121」が3件、「298」が2件と重複しています。ここから各学生ごとに最新(最大ID)のレコードのみを抽出することを目指します。
4. 複数カラムに対するDISTINCT的な抽出クエリ
ここでは、GROUP BYとMAX()関数を組み合わせたサブクエリを使用します。各StudentIdグループの中で最大のInstructorIdを持つ行だけを選択することで、実質的に重複のない結果を取得できます。
mysql> select InstructorId,StudentId,TechnicalSubject from selectDistinctDemo
-> where InstructorId IN
-> (
-> select max(InstructorId) from selectDistinctDemo
-> group by StudentId
-> )
-> order by InstructorId desc;
5. 実行結果
+--------------+-----------+------------------+ | InstructorId | StudentId | TechnicalSubject | +--------------+-----------+------------------+ | 6 | 397 | C# | | 5 | 298 | SQL Server | | 3 | 121 | MySQL | +--------------+-----------+------------------+ 3 rows in set (0.10 sec)
解説:なぜこのクエリが機能するのか
このクエリの仕組みを順を追って説明します。
- サブクエリ部分:
select max(InstructorId) ... group by StudentIdにより、各StudentIdグループ内で最も大きいInstructorId(= 最新のレコード)が返されます。この例では「3」「5」「6」が該当します。 - WHERE句:
InstructorId IN (...)によって、上記で得られたIDに一致する行だけがメインクエリから選択されます。 - ORDER BY句:
InstructorId descにより、結果が降順に並べ替えられます。
このように、単純なDISTINCTでは対応しきれない「特定カラムの値ごとに1件だけ残したい」という要件は、GROUP BY + MAX()(またはMIN())とIN演算子を組み合わせることでスマートに解決できます。
なお、MySQL 8.0以降ではウィンドウ関数(ROW_NUMBER())を使った方法も利用可能なので、より柔軟な実装が必要な場合はそちらも検討するとよいでしょう。
-
MySQLでSELECT文の中にCASE式を使う方法を解説
MySQLでは、SELECT文の中でCASE WHEN式を使うことで、条件に応じた値を返すことができます。本記事では、具体的なサンプルを使いながら、その基本的な使い方をわかりやすく解説します。1. サンプルテーブルの作成まず、デモ用のテーブルを作成します。mysql> create table DemoTable -> ( -> FirstName varchar(20), -> Score int -> );Query OK, 0 rows affected (0.63 sec)2. テストデータの挿入INSERTコマンドを使って、いくつか
-
MySQLでカスタム列に複数の値を設定する方法|UNION ALLの使い方を実例で解説
はじめにMySQLでカスタム列(計算結果を出力する列)に複数の値を持たせたい場合、UNION ALLを利用すると簡単に実現できます。本記事では、実際にテーブルを作成し、UNION ALLを使って1つの列から複数の計算結果を取得する手順を、サンプルコードと実行結果あわせて詳しく解説します。サンプルテーブルの作成まず、動作確認用のテーブルを作成しましょう。mysql> create table DemoTable1987 ( UserValue int ); Query OK, 0 rows affected (2.90 sec)レコードの挿入INSERT文を使って、