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

【MySQL】FIND_IN_SET()を使ってカスタム順序でORDER BYソートする方法

はじめに

MySQLでは、通常のORDER BY句は数値や文字列の昇順・降順でソートしますが、特定の値を優先した独自の順序(カスタム順序)で並べ替えたいケースがあります。例えば、ユーザーのステータスを「BLOCKED → AT WORK → OFFLINE → BUSY」のように任意の順番で表示したい場合です。

このようなカスタムフィールド値での並べ替えを実現するには、FIND_IN_SET()関数を使用します。本記事では、実際にテーブルを作成しながら、その使い方をわかりやすく解説します。

サンプルテーブルの作成

まず、デモ用のテーブルを作成しましょう。以下のSQLでは、ユーザーIDとユーザーステータスを持つテーブル「DemoTable677」を定義しています。

mysql> create table DemoTable677(
    UserId int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    UserStatus text
);
Query OK, 0 rows affected (1.07 sec)

テストデータの挿入

次に、INSERTコマンドを使っていくつかのレコードを追加します。ステータスには「BUSY」「AT WORK」「OFFLINE」「BLOCKED」の4種類を登録します。

mysql> insert into DemoTable677(UserStatus) values('BUSY');
Query OK, 1 row affected (0.23 sec)
mysql> insert into DemoTable677(UserStatus) values('AT WORK');
Query OK, 1 row affected (0.17 sec)
mysql> insert into DemoTable677(UserStatus) values('OFFLINE');
Query OK, 1 row affected (0.18 sec)
mysql> insert into DemoTable677(UserStatus) values('BLOCKED');
Query OK, 1 row affected (0.17 sec)

登録データの確認

SELECT文ですべてのレコードを表示してみましょう。

mysql> select *from DemoTable677;

実行結果は以下の通りです。

+--------+------------+
| UserId | UserStatus |
+--------+------------+
|      1 | BUSY       |
|      2 | AT WORK    |
|      3 | OFFLINE    |
|      4 | BLOCKED    |
+--------+------------+
4 rows in set (0.00 sec)

現時点では、挿入した順番どおりにレコードが並んでいます。

FIND_IN_SET()でカスタム順序に並べ替える

ここからが本題です。FIND_IN_SET()関数をORDER BY句と組み合わせることで、指定した値リストの順序に従ってソートできます。

FIND_IN_SET(検索対象の列, '値1,値2,値3,...') の形式で記述すると、各レコードが値リスト内の何番目に位置するかを数値として返し、その数値を基準に並べ替えが行われます。

以下のクエリでは、「BLOCKED」を先頭に、「AT WORK」「OFFLINE」「BUSY」の順で表示するよう指定しています。

mysql> select *from DemoTable677 
    ORDER BY FIND_IN_SET(UserStatus, 'BLOCKED,AT WORK,OFFLINE,BUSY');

実行結果:

+--------+------------+
| UserId | UserStatus |
+--------+------------+
|      4 | BLOCKED    |
|      2 | AT WORK    |
|      3 | OFFLINE    |
|      1 | BUSY       |
+--------+------------+
4 rows in set (0.03 sec)

ご覧のとおり、リストで指定した順序どおりにレコードが並び替えられました。「BLOCKED」が最初に、「BUSY」が最後に表示されています。

FIND_IN_SET()の仕組みと注意点

仕組み

FIND_IN_SET()は、第2引数の文字列リスト(カンマ区切り)の中から第1引数の値を探し、見つかった位置(1始まりのインデックス)を返します。ORDER BY句内で使うことで、その位置情報をもとにソートが実現します。

  • 「BLOCKED」→ リスト内の位置 1
  • 「AT WORK」→ リスト内の位置 2
  • 「OFFLINE」→ リスト内の位置 3
  • 「BUSY」→ リスト内の位置 4

注意点

  • リスト外の値の扱い: 第2引数のリストに含まれない値は 0 を返すため、それらのレコードはリスト内の値より先頭に表示されます。意図しない順序になる場合は、条件分岐や追加のソートキーを検討しましょう。
  • NULLの扱い: 対象の列がNULLの場合、FIND_IN_SET()はNULLを返します。
  • パフォーマンス: 大量データに対してFIND_IN_SET()によるソートを行うと、インデックスを利用できず処理が遅くなる可能性があります。大規模なテーブルでは、ENUM型への変更やCASE式、別途ソート用の順序列を持たせる方法も検討するとよいでしょう。

まとめ

MySQLで独自の順序(カスタム順序)に従ってレコードを並べ替えたい場合は、ORDER BY句とFIND_IN_SET()関数を組み合わせるのが手軽で効果的です。ステータス管理や優先度表示など、実務でもよく使われるテクニックなので、ぜひ覚えておきましょう。データ量が多い場合はパフォーマンス面にも配慮し、適切な設計を選択してください。

  1. MySQL:ORDER BY FIELDとOR条件を組み合わせた優先順位付き並べ替えの方法

    MySQLでは、ORDER BY句とFIELD()関数を組み合わせることで、特定の値を優先的に並べ替えることができます。本記事では、WHERE句のOR条件とFIELD()関数を併用する方法を、実際のサンプルコードとともにわかりやすく解説します。 サンプルテーブルの作成 まず、動作確認用のテーブルを作成しましょう。 mysql> create table DemoTable1884     (     Marks int     ); Query OK, 0 rows

  2. MySQLでGROUP BYのように特定の1行だけ更新する方法|ORDER BYとLIMITを活用したUPDATE文の書き方

    MySQLでは、UPDATE文の中でGROUP BYを直接使用することができません。しかし、「同じ値を持つ複数のレコードの中から、最初の1行だけを更新したい」というケースは実際の開発でよく発生します。 そんなときに役立つのが、ORDER BYとLIMITを組み合わせたUPDATE文です。この記事では、サンプルテーブルを使いながら、その具体的な手順をわかりやすく解説します。 1. サンプルテーブルを作成する まず、従業員情報を格納するテーブル「DemoTable2018」を作成します。テーブルには、自動採番される主キー「EmployeeId」、従業員名「EmployeeName」、給与「Emp