前回の記事、【初級編⑫】なんとなく書いていたSELECT文を根本から理解する(1/2)では、SELECT文が実行される仕組みをExcelを使って説明しました。
今回は、そのSELECT文の中の各句(SELECTやFROMなど)が実行される順番について説明したいと思います。
目次
SELECT文の内部処理を見てみる
SELECT文を含めSQLは、実行すると全体が一気に処理されてその最終結果だけしか画面に表示されません。ただ、SQLServerの内部ではSELECTやFROMなどの”句”毎に分解して解析され実行されています。
実際にSELECT文を実行する時にSQLServerが内部でどんな処理をしているかを見てみましょう。
SELECT 社員番号, 名前, 性別, 給料, 給料 * 12 AS '年収' FROM Table_Syain WHERE 性別 = '女' ORDER BY 年収 ------------------------------------------------------------------ 社員番号 名前 性別 給料 年収 ----- -------------------- ---- ----------- ----------- 00006 前田 六実 女 180000 2160000 00003 鈴木 三つ子 女 250000 3000000 (2 行処理されました)
クエリエディタには「推定実行プランの表示」というボタンがありますので、これをクリックすると「実行プラン(実行計画とも言う)」というものを表示できます。実行プランとは、まさにSQLServerが内部で解析した情報になります。
まだ詳しくは分からなくていいのですが、今回の実行プランの部分を拡大してみます。右から左に処理が流れているのですが、SELECT文が完了するまでに、①~③の3つの処理が実行されていることが分かります。①は「性別」が[女]のレコードを検索する処理で、その検索結果に対して②「給料」* 12 で年収を求める処理があり、③で「年収」の順番に並び替え処理が実行されています。
SELECT文の各句が実行される順番
SELECT文が実行される時に、各句が実行される順番を下に記載します。
順番 | 句 | 内容 |
---|---|---|
① | FROM句 | 実行対象のテーブルを指定します |
② | WHERE句 | テーブルに対してレコードの抽出条件を指定します |
③ | GROUP BY句 | レコードをグループ化します |
④ | HAVING句 | グループ化した結果に対して抽出条件を指定します |
⑤ | SELECT句 | 取得(表示)する列を指定します |
⑥ | ORDER BY句 | 取得した列を並び替えます |
FROM句
全ての処理の中で、最初にFROM句が実行されます。FROM句では実行しようとしているSELECTの対象を指定するのですが、最初にこれをしないとどのテーブルに対して命令を実行するのか分からないので処理ができませんね。
テーブル結合もFROM句に書きますが、先にテーブル結合をしておいて、結合が全て終わった結果のテーブルに対して、後続の処理が実行されます。
WHERE句
2番目に、指定したテーブル(結合した結果)に対して、対象とするレコードの絞り込みを行います。不要なレコードは取り除くという処理になります。
ここで注意なのは、いくらGROUP BYやHAVING等を使っていても、WHEREはそもそも対象テーブル全件に対して先に絞り込みを掛けておき、GROUP BYはWHEREで絞り込まれた結果残ったレコードに対してのみグループ化されるということです。
社員テーブルに対して、男女別の人数を集計してみるとします。
例えば、年齢が30才未満の社員に対して、男女別の人数を集計すると、確かに人数が変わっていることが分かります。
これは、GROUP BY句で集計されるのは、あくまでWHERE句で絞り込んだ結果のレコードに対してだからです。
GROUP BY句
前述のWHERE句でも触れましたが、GROUP BY句は「WHERE句で絞り込まれた結果のレコード」に対してグループ化を行います。
またグループ化というのは、集計することになるので、集計対象のキーにした列以外は取得できません。先ほども実行しましたが、社員の男女別の人数を集計してみます。
この時、SEELCTしているのは「性別」と「COUNT(性別)」だけですが、「性別」以外の列はSELECTすることができません。なぜなら、複数レコードを纏めてグループ化している為、例えば「社員番号」を取得するにしても、どのレコードの社員番号を取得すれば良いかが分からないからです。
今回の場合、男は6人居てその6人の中からどれを選べばいいかの基準がありません。
レコードを選択する基準が無いからSELECTできないのだから、SELECTするにはどのレコードを選べば良いのかを指定してあげればOKです。例えば簡単なやり方だと、数字だったら最大値、もしくは最小値を出す方法です。
SELECT MIN(社員番号) AS '社員番号の最小値' ,性別 , COUNT(性別) AS '性別毎の人数' FROM Table_Syain GROUP BY 性別 社員番号の最小値 性別 性別毎の人数 -------- ---- ----------- 00003 女 2 00001 男 6 (2 行処理されました)
HAVING句
HAVING句は、GROUP BY句でグループ化した後、その集計対象に条件を指定します。
句 | 内容 |
---|---|
WHERE | テーブルのレコード全件に対して抽出する |
HAVING | GROUP BY句で集計した対象レコードに対して抽出する |
先の男女別の人数を求める際は、「性別」で集計してカウントを取りましたが、HAVING句の使い方は、この性別毎に集計した結果に対して条件を指定します。例えば次の様なSQLだと、
SELECT 性別 ,COUNT(性別) AS '性別毎の人数' FROM Table_Syain GROUP BY 性別 HAVING COUNT(性別) >= 3 性別 性別毎の人数 ---- ----------- 男 6 (1 行処理されました)
同じ性別のレコードをグループ化し、そのレコードの件数が3以上のもの、という条件指定になります。
SELECT句
ここまでやって、やっとSELECT句の登場です。基本的に、この状態で出力対象のレコード件数は揃っていて、あとは取得したい列を指定するだけです。Excelで言うと不要な列を非表示にするだけ(表示したい列のみを残す)です。
前回の記事で説明したSELECT文「社員マスタに対して、女性社員の年収を求めて、年収の昇順に並べたリスト」を例にします。
SELECT句が実行されるタイミングでは、ちょうど下の図のWHERE句で絞り込みが終わった状態です
この状態から、必要な列だけSELECTしたり、「給料」 * 12 をして「年収」列を取得したりしていました。
ORDER BY句
SELECT句が実行され、取得する列が決まったら、最後にORDER BY句で並び替えを指定します。Excelで加工する時と同じ感覚かと思います。
SQLを習得するには、今回の記事で書いた「どういう順番で各句が実行されるか?」の理解が必須です。それを、頭の中でシュミレートできるようになれば、複雑なSELECT文でもスラスラ書けるようになるでしょう。
DB未経験のため困っていましたが今まで見てきたどんな資料よりもとても分かりやすく助かりました。ありがとうございました。