SQLのSELECT文を書く際、キーワードの役割や各句の順番がよくわからなくなる(おじさんだからだ)。そこで、同文で使われる主要な句の種類と順番の覚え方をまとめてみる。

なお、SQLiteのドキュメントを参考にしているが、どのSQLでも大枠は変わらないはずである。

SELECT文で使う主なキーワードの種類

それぞれのキーワードが何をしているかを理解すれば、それを記述する順番は考えればわかるようになる。きっとなるはずだ。

キーワード 概要
テーブル名1 INNER JOIN テーブル名2 ON 条件式 条件式に基づいてテーブル名1とテーブル名2を横に結合する。
WHERE 条件式 条件式に基づいて行をフィルタリングする。
GROUP BY 列名 HAVING 条件式 指定した列の値が同じ行を1つのグループにまとめる。グループをフィルタリングしたい時はHAVING句を使う。こちらは任意。
ORDER BY 列名 指定された列名に基づき、結果を並び替える。
LIMIT 行数 必要な行数を、上から数えた行数で取得する。

目的はSELECT文の構造の大枠を把握すること(そして各句の記述順を覚える助けとすること)であるため、各キーワードのオプションについては省略する。

個人的な感覚では、混乱しやすいのはWHEREの位置ではないかと思う。なぜ混乱しやすいかと言えば、WHEREが何に対する条件なのか直感的に把握しづらいためだ。

改めて、SELECT文の処理の流れを整理してみたい。

SELECT文の処理の流れ

  1. データを取得するテーブルを定める…FROM
  2. 2つ以上のテーブルが必要なら1と結合する…JOIN
  3. 一部の行を取得したい時はフィルタリングする…WHERE
  4. グループで集約したい時はグループ化する…GROUP
  5. 一部のグループを取得したい時はフィルタリングする…HAVING
  6. 並び替えたい時は並び替える…ORDER BY
  7. 取得する数を制限したいときは制限する…LIMIT

整理した。先のテーブルとだいたい同じだ。とはいえ、取得したいデータに応じて、SELECT文が合理的に構成されていることがわかる。

句の順番の覚え方のコツ

SELECT文の処理の流れに基づいて、各句を覚える際のコツをまとめる。

FROMとJOINはセット

JOINをどこに使うかも、地味にややこしく感じる。これはFROMとセットで使われることを覚えておけば混乱しない。

sql
SELECT
    *
FROM --ここからはONまでは、1つの一塊として理解する
    table1
INNER JOIN
    table2
ON
    table1.column = table2.column;

また、ONは結合条件であるが、見方を変えればフィルタリング条件である。そのため、この時点ではWHEREはいらない。

WHEREは個々の行を絞る

WHEREは、FROMで得られたテーブル(単純なテーブル、あるいは結合して得られたテーブル)の個々の行をフィルタリングするために使う。

JOINFROMのオプションと理解していれば、単純な構造なので覚えやすいかと思う。

sql
SELECT
    *
FROM
    table1
/* INNER JOIN --- コメントアウトしてある箇所は任意
    table2
ON
    table1.column = table2.column */
WHERE
    column IS NOT NULL;

ちなみに’where’は、数学的な定義や証明の中で、式や変数が特定の特性を持つことを示すために使われる。SQLのWHEREキーワードは、このニュアンスで使われている。

HAVINGはGROUP BYの条件文

SQLには、ONWHEREINなど、条件のニュアンスを持つキーワードが複数存在する。GROUPをフィルタリングするためにどのキーワードを使うかも、慣れるまでは悩ましい。

身も蓋もないが、『ある特定の条件を「持っている」グループを選ぶ』というように覚えるしかない。グループは何かを「持っている」ため、ぼっちには居る「場所」がない、とでも覚えておく。

sql
SELECT
    SUM(column)
FROM
    table1
/* INNER JOIN --- コメントアウトしてある箇所は任意
    table2
ON
    table1.column = table2.column;
WHERE
    column IS NOT NULL */
GROUP BY column
HAVING SUM(column) > 0;

また、HAVINGキーワードは基本的に集約関数と併用する点にも注意したい。これは、HAVING句がグループ化された結果に対して適用される条件であるためだ。HAVING句が偽のグループはそのまま破棄される。

なお、HAVING句うに集約関数以外を指定すると、任意の行が選ばれる。エラーは起きないが、結果は予測しづらくなる。

ORDER BYは結果を並び替える

ORDER BYは、諸々の操作をした結果をソートするために使う。そのため書く場所は最後、ではなく最後から2番目である。

とはいえ結果が出た後に実行されることを理解していれば、書く場所に迷うことはない。

sql
SELECT
    SUM(column)
FROM
    table1
/* INNER JOIN --- コメントアウトしてある箇所は任意
    table2
ON
    table1.column = table2.column;
WHERE
    column IS NOT NULL
GROUP BY column
HAVING SUM(column) > 0 */
ORDER BY column;

LIMITは最後に取得する結果の行の範囲を絞る

LIMITは最後に書く。LIMITという単語のイメージにも、なんとなく限界感があるので、こちらも覚えやすいかと思う。

sql
SELECT
    SUM(column)
FROM
    table1
/* INNER JOIN --- コメントアウトしてある箇所は任意
    table2
ON
    table1.column = table2.column;
WHERE
    column IS NOT NULL
GROUP BY column
HAVING SUM(column) > 0
ORDER BY column */
LIMIT 10;

おしまい。

参考