MySQL
 Computer >> コンピューター >  >> プログラミング >> MySQL

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())を使った方法も利用可能なので、より柔軟な実装が必要な場合はそちらも検討するとよいでしょう。

  1. 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コマンドを使って、いくつか

  2. MySQLでカスタム列に複数の値を設定する方法|UNION ALLの使い方を実例で解説

    はじめにMySQLでカスタム列(計算結果を出力する列)に複数の値を持たせたい場合、UNION ALLを利用すると簡単に実現できます。本記事では、実際にテーブルを作成し、UNION ALLを使って1つの列から複数の計算結果を取得する手順を、サンプルコードと実行結果あわせて詳しく解説します。サンプルテーブルの作成まず、動作確認用のテーブルを作成しましょう。mysql> create table DemoTable1987 ( UserValue int ); Query OK, 0 rows affected (2.90 sec)レコードの挿入INSERT文を使って、