MySQL 入門

MySQL ORDER BY 句

データベースからデータを取得する際、結果が返される順序はデータの使いやすさや分析効率に大きな影響を与えます。SQLの ORDER BY 句を使用すると、一つまたは複数の指定したカラムに基づいて、SELECT 文の結果セットをソート(並び替え)することができます。この句を活用することで、データを昇順または降順に並べ、情報の提示方法を自在にコントロールすることが可能になります。

1. ORDER BY を使用した基本ソート

ORDER BY の最も基本的な使い方は、単一のカラムを指定してソートすることです。デフォルトでは、ORDER BY は結果を昇順でソートします。明示的に順序を定義する場合、昇順には ASC キーワードを、降順には DESC キーワードを使用します。

1.1 単一カラムの昇順ソート

昇順(Ascending)でソートすると、数値は最小値から最大値へ、文字列はアルファベット順(AからZ)、日付は古いものから新しいものへと並びます。

例 1:氏名で顧客をソートするcustomer_idfirst_namelast_namecity カラムを持つ customers(顧客)テーブルがあるとします。すべての顧客を取得し、姓(last_name)のアルファベット順に並べるには以下のクエリを実行します。

SELECT
    customer_id,
    first_name,
    last_name,
    city
FROM
    customers
ORDER BY
    last_name ASC; -- last_name(姓)を基準に昇順でソートすることを明示

このクエリは全顧客の詳細を返しますが、行の並びは姓が 'A' で始まる顧客が最初になり、次に 'B' と続いていきます。

例 2:価格で製品をソートするproduct_idproduct_nameprice を含む products(製品)テーブルを想定します。製品を安い順にリストアップするには以下のように記述します。

SELECT
    product_id,
    product_name,
    price
FROM
    products
ORDER BY
    price; -- ASC はデフォルト値のため省略可能

出力結果には、まず価格の低い製品が表示され、徐々に価格の高い商品へと遷移していきます。

1.2 単一カラムの降順ソート

降順(Descending)ソートは、並べ替えのルールを反転させます。数値は最大値から最小値へ、文字列は Z から A へ、日付は新しいものから古いものへと並びます。

例 3:入社日で従業員をソートするemployees(従業員)テーブルに employee_idfirst_namelast_namehire_date が含まれているとします。最近入社した従業員を最初に確認したい場合は以下のようにします。

SELECT
    employee_id,
    first_name,
    last_name,
    hire_date
FROM
    employees
ORDER BY
    hire_date DESC; -- hire_date(入社日)を基準に降順でソート

このクエリは、最も最近雇用された従業員から順に従業員リストを表示します。

例 4:販売数量で売れ筋商品を特定するsales(売上)テーブルに item_idquantity_sold(販売数量)が含まれている場合、最も売れている商品を特定するには以下のように記述します。

SELECT
    item_id,
    quantity_sold
FROM
    sales
ORDER BY
    quantity_sold DESC;

結果として、quantity_sold が高い順に商品が表示されます。

2. 複数カラムによるソート

ORDER BY 句には複数のカラムを指定することができます。複数のカラムを指定した場合、データベースはまず最も左側に指定されたカラムでソートを行います。もし最初のカラムに同じ値が存在する場合、次に二番目のカラムを使用してそれらの行を並び替えます。ORDER BY 句内の各カラムには、個別に ASC または DESC を指定することが可能です。

例 5:まず都市でソートし、次に姓でソートする
顧客をまず居住都市ごとにまとめ、同じ都市内の顧客をさらに姓で並べ替えるには以下のようにします。

SELECT
    customer_id,
    first_name,
    last_name,
    city
FROM
    customers
ORDER BY
    city ASC,        -- まず city(都市)で昇順ソート
    last_name ASC;   -- 同じ都市内で last_name(姓)を昇順ソート

このクエリを実行すると、'New York' の全顧客が姓の順に並び、その次に 'London' の全顧客が姓の順に並ぶ、といった形式で結果が返されます。

例 6:注文ステータス(降順)の後に注文日(降順)でソートするorder_idcustomer_idorder_dateorder_status を持つ orders(注文)テーブルを考えます。最近完了した注文を先に見たいが、保留中の注文も確認したい、かつ同じステータス内では最新のものを優先したい場合は以下のようになります。

SELECT
    order_id,
    customer_id,
    order_date,
    order_status
FROM
    orders
ORDER BY
    order_status DESC, -- ステータスでソート(例:'Completed' を 'Pending' より先に)
    order_date DESC;   -- 次に order_date でソート(最新を優先)

もし order_status が文字列の場合、昇順では 'Completed' は 'Pending' の後に来ます。ここで DESC を使用することで 'Pending' を 'Completed' の前に持ってくる(論理的なグループ化)ことができます。また、ステータスコード(例:1=保留、2=完了)を使用している場合、DESC を使えば完了(2)が保留(1)より先に表示されます。

3. カラム位置によるソート

カラム名で参照する代わりに、SELECT リスト内での位置(インデックス)で参照することも可能です。この方法は可読性が低く、SELECT リストの変更(カラムの追加や削除)によってクエリが壊れる可能性があるため、本番環境のコードでは一般的に推奨されませんが、有効な構文の一つです。

例 7:カラム位置でソートする
例 3 の employees テーブルを使用します。

SELECT
    employee_id, -- 第 1 カラム
    first_name,  -- 第 2 カラム
    last_name,   -- 第 3 カラム
    hire_date    -- 第 4 カラム
FROM
    employees
ORDER BY
    4 DESC; -- SELECT リストの 4 番目のカラム(つまり hire_date)で降順ソート

このクエリは例 3 と同じ結果をもたらしますが、hire_date という名前の代わりに位置番号 4 を使用しています。

4. WHERE 句と組み合わせたソート

SELECT 文の中で WHERE と ORDER BY を同時に使用する場合、ORDER BY 句は通常 WHERE 句の後に配置します。データベースはまず WHERE 句で各行をフィルタリングし、その後にフィルタリングされた結果セットを ORDER BY でソートします。

例 8:顧客をフィルタリングしてからソートする
'New York' の顧客のみを抽出し、姓でソートします。

SELECT
    customer_id,
    first_name,
    last_name,
    city
FROM
    customers
WHERE
    city = 'New York' -- ニューヨークの顧客をフィルタリング
ORDER BY
    last_name ASC;    -- フィルタリングされた結果を姓でソート

このクエリはまず city が 'New York' であるすべての顧客を選択し、その特定の顧客たちだけをアルファベット順に並べ替えます。これは、ORDER BY がデータを整理する前に、WHERE 句がデータの範囲をいかに絞り込むかを示しています。

5. NULL 値とソート

NULL(空)値を含むカラムをソートする場合、データベースシステムによって NULL の扱いが異なることがあります。MySQL では、ソート時に NULL 値は「最小の可能性のある値」として扱われます。したがって、ASC(昇順)ソートでは NULL が最初に出現し、DESC(降順)ソートでは最後に出現します。

例 9:NULL 値を含むソート
最上位の従業員において manager_id が NULL になる可能性がある employees テーブルを想定します。

SELECT
    employee_id,
    first_name,
    manager_id
FROM
    employees
ORDER BY
    manager_id ASC; -- NULL 値が最初に表示される

昇順ソートでは、manager_id が NULL の従業員(通常はトップマネジメント層)がリストの先頭に来ます。

SELECT
    employee_id,
    first_name,
    manager_id
FROM
    employees
ORDER BY
    manager_id DESC; -- NULL 値が最後に表示される

降順ソートでは、manager_id が NULL の従業員はリストの最後に表示されます。

特に NULL が「未知」や「不適用」を意味するカラムを扱う際、この挙動を理解しておくことはソート結果を解釈する上で非常に重要です。