このページでは、SQL文の種類、SELECT文が動く順番、WHEREやLIKEなどの条件の書き方、GROUP BYとHAVINGによる集計がわかります。
- 一言で言うと:
- 関係データベースを操作する標準言語SQLの話。中心は、データを取り出すSELECT文
- 条件の書き方、グループ化、表の結合(内結合・外結合)、副問合せ、WITH句・CASE式、データの追加・変更・削除と、参照制約がある表の更新まで出てくる
SQL文の種類 → SELECTの骨組み(FROM→WHERE→GROUP BY→HAVING→SELECTの順)→ 条件・集計・並べ替え → 表をつなぐ(内結合、外結合、COALESCE、相関名)→ 問合せの中の問合せ(副問合せ、EXISTS)→ 一時表と場合分け(WITH句、CASE式)→ 書き換える(INSERT、UPDATE、DELETE、参照動作)
覚え方の軸
- SELECTは「書く順」と「動く順」が違う
- 書く順:SELECT → FROM → WHERE → GROUP BY → HAVING
- 動く順:FROM → WHERE → GROUP BY → HAVING → SELECT(最後にORDER BY)
- WHEREは行を選ぶ、HAVINGはグループを選ぶ
- NULLは「=」で比べられない
- 判定はIS NULL / IS NOT NULL。比較演算子でNULLと比べると不定(unknown)
- 集合関数はNULLを除いて計算する(ただしCOUNT(*)は行を全部数える)
SQL文の種類:定義・操作・制御・カーソル
- SQL:
- 関係データベースにおける標準的なデータベース言語
- データの検索、挿入、更新、削除の4つの基本操作のほか、スキーマ、表、ビュー、インデックス(索引)などのデータベースオブジェクトを定義するSQL文や、トランザクションを制御するSQL文などがある
- DDLとDML:
- SQLは、DDL(Data Definition Language:データ定義言語)と、DML(Data Manipulation Language:データ操作言語)などに大きく分けられる
主なSQL文(★)
| 分類 | SQL文 | 中身 |
|---|---|---|
| データベースオブジェクトの定義・変更 | CREATE | データベースオブジェクトの定義 |
| DROP | データベースオブジェクトの削除 | |
| ALTER | データベースオブジェクトの定義変更 | |
| データ操作 | SELECT | データの検索(問合せ) |
| INSERT | データの挿入(追加) | |
| UPDATE | データの更新 | |
| DELETE | データの削除 | |
| データ制御 | GRANT | 表やビューに対するアクセス権(読取権限、挿入権限、更新権限、削除権限)の付与 |
| REVOKE | アクセス権の削除(取消) | |
| COMMIT | トランザクション更新処理の確定 | |
| ROLLBACK | トランザクション更新処理の取消 | |
| カーソル定義・操作 | DECLARE CURSOR | カーソルの割当て(カーソルの宣言・定義) |
| OPEN | カーソルのオープン | |
| FETCH | カーソルが指し示す行データの取り出し | |
| CLOSE | カーソルのクローズ |
- カーソル定義・操作:
- 親言語方式などで使うSQL文
- 親言語方式は、プログラムの中にSQL文を組み込んでデータベースにアクセスする方式。埋込みSQLともいう
- 勉強のコツ:
- 試験で最も多く出るのはデータ操作文(特にSELECT)
- 複雑なSQL文を読めるように、暗記ではなく、規則を理解することに重点を置く
SELECT(問合せ):動く順番を押さえる(★)
SELECT(問合せ)の基本形
SELECT [ALL | DISTINCT] 選択リスト
FROM 参照表リスト
[WHERE 選択条件や結合条件]
[GROUP BY グループ化列名リスト]
[HAVING グループ選択条件]
- 記号の意味:
- [ ] の中は省略できる。| は「または」
- リスト:
- 列名や表名などを、カンマ(,)で区切って並べたもの
- 表式:
- FROM句からHAVING句までのこと
- 評価・実行の順番:
- 「表式(FROM句 → WHERE句 → GROUP BY句 → HAVING句)→ SELECT句」の順に評価・実行し、その結果を導出表として出力する
- 各句は、前の句が作った表を受け取り、処理した結果を次の句に渡す
- 仮想表(中間表):
- 各句で作られる表のこと
- ORDER BY句:
- 問合せ文の後にORDER BY句を付けると、結果を並べ替えられる
各句の処理概要(★)
| 句 | 中身 |
|---|---|
| FROM句 | 処理の対象となる参照表(表、ビューなど)を指定する。1つならその表を、複数なら(概念的に)直積を作って次に渡す |
| WHERE句 | 特定の行を選択する条件や、表を結合する条件を指定する。条件を満たす行を取り出して次に渡す |
| GROUP BY句 | グループ化する列を指定する。指定された列でグループ化した結果(グループ表)を次に渡す |
| HAVING句 | 特定のグループを抽出する条件を指定する。条件を満たすグループだけを次に渡す。GROUP BY句がなければ、前の表全体を1つのグループとして扱う |
| SELECT句 | 取り出す列(全列なら「*」。同じ列の複数指定も可)、算術式、集合関数、定数を指定する。列名ならその値、算術式ならその計算結果、集合関数なら集計結果、定数ならその値を、導出表の列(導出列)として出力する |
- DISTINCTとALL:
- DISTINCTを指定すると、重複行が取り除かれる
- ALLを指定すると、重複行も含めて出力する。省略時はALL
- SELECTの動く順の例え:
- 料理で、①材料を全部出す(FROM)→ ②傷んだものを除く(WHERE)→ ③種類ごとに分ける(GROUP BY)→ ④少なすぎる種類は除く(HAVING)→ ⑤お皿に盛る(SELECT)→ ⑥並べる(ORDER BY)
基本的なSQL問合せ:条件・集計・並べ替え(★)
① 選択条件の指定
- WHERE句とSELECT句:
- WHERE句に選択条件を書くと、特定の行を取り出せる(選択演算)
- SELECT句に列名を書くと、特定の列を取り出せる(射影演算)
- 論理演算子:
- AND、OR、NOTを使うと、複数の条件を組み合わせられる
比較演算子一覧
| 演算子 | 意味 | 使用例 |
|---|---|---|
| = | 等しい | WHERE 列A = 30 |
| <> | 等しくない | WHERE 列A <> 30 |
| > | より大きい | WHERE 列A > 30 |
| < | より小さい | WHERE 列A < 30 |
| >= | 以上 | WHERE 列A >= 30 |
| <= | 以下 | WHERE 列A <= 30 |
例:特定の行・列を取り出す
- 社員表:
- (1101、青木花子、19、S1)、(1102、青木進、22、S1)、(1201、石井健、24、S2)、(1202、小林誠、28、S2)、(1301、岡本恵、30、S3)
- 列は、社員コード、社員名、年齢、部門コード
SELECT 社員コード, 社員名
FROM 社員
WHERE 年齢 >= 24 AND
年齢 <= 28
- 結果:
- (1201、石井健)、(1202、小林誠)
- NGな書き方:
- 「24 <= 年齢 <= 28」と書くとエラーになる。ANDで2つに分けて書く
② IS NULL述語
- IS NULL述語:
- 列の値が空値(NULL)かどうかを判定するときは、「列名 = NULL」ではなく、「列名 IS NULL」と書く
- 例えば、所属部門が決まっていない社員は「部門コード IS NULL」
- 所属部門が決まっている社員は「部門コード IS NOT NULL」
- NULLとの比較は不定:
- 列の値とNULLを比較演算子で比べた結果は、常に不定(unknown)になる
- 例えば、A=20、B=10、CがNULLのとき、(A>C)OR(A>B)は、「不定 OR 真」で真になる
- 不定の例え:
- 「Cさんの年齢は不明」のとき、「AさんはCさんより年上?」には答えられない(不定)。でも「AさんはCさんより年上、またはBさんより年上?」なら、Bさんより年上なので「はい(真)」と言える
③ BETWEEN述語
- BETWEEN述語:
- 列の値が「値1〜値2(値1、値2を含む)」の範囲に入るかを判定する
- 24歳以上28歳以下なら、「年齢 BETWEEN 24 AND 28」
- NOT BETWEEN:
- 「年齢 NOT BETWEEN 24 AND 28」は、24歳以上28歳以下でない社員
- 「年齢 < 24 OR 年齢 > 28」と同じ
- 日付の範囲:
- 年月日の範囲チェックにも使う
- 例えば、「納入日 BETWEEN ‘2025-04-01’ AND ‘2025-04-30’」
④ IN述語
- IN述語:
- 列の値が、括弧の中の値リストのどれかと等しいかを判定する
- 例えば、「年齢 IN (24, 25, 26, 27, 28)」で24歳以上28歳以下
- NOT IN:
- INの前にNOTを付けると、24歳以上28歳以下でない社員
- IN+副問合せ:
- 括弧の中に副問合せを書ける(副問合せは後述)
- 例えば、「WHERE 年齢 IN (SELECT 年齢 FROM 社員 WHERE 年齢 BETWEEN 24 AND 28)」でも同じ結果
⑤ LIKE述語
- LIKE述語:
- 列の値が、あるパターン値に合うかを判定する
- 「列名 LIKE パターン値」と書くと、パターンマッチングが行われる
- パターン文字:
- %は、0文字以上の任意の文字列。例えば「a%b」は、aで始まりbで終わる任意の長さの文字列
- _(アンダースコア)は、任意の1文字。例えば「a__b」は、aで始まりbで終わる4文字の文字列
- 例:
- 社員名が「青木」で始まる社員は、「社員名 LIKE ‘青木%’」
- 結果は、(1101、青木花子)、(1102、青木進)
- LIKEの例え:
- %は「何文字でもよいワイルドカード」、_は「1マス分の空欄」
⑥ グループ化
- GROUP BY句:
- 取り出した行を、指定した列の値でグループ化し、グループごとの合計、平均値、最大値などを求める
- HAVING句:
- 条件に合ったグループだけを取り出す
- 例:
- 2人以上が所属する部門の、部門コード、所属人数、平均年齢を求める
SELECT 部門コード,
COUNT(*) AS 所属人数, AVG(年齢) AS 平均年齢
FROM 社員
GROUP BY 部門コード
HAVING COUNT(*) >= 2
- 動き:
- 「GROUP BY 部門コード」で、部門コードごとにグループ化する
- 「HAVING COUNT(*) >= 2」で、行数が2以上のグループを取り出す
- グループごとに、部門コード、所属人数、平均年齢を求める
- 結果:
- (S1、2、20.5)、(S2、2、26)
- S3は1人なので、条件を満たさない
- 検算:
- S1は(19 + 22)÷ 2 = 20.5、S2は(24 + 28)÷ 2 = 26
- AS:
- 列や表に別名を付けるときに使う
- 省略できるが、SELECT句では省略しないことが多い
- GROUP BYを使うときのSELECT句:
- SELECT句に書けるのは、基本的に、グループ化列の列名、集合関数、定数などの値式だけ
- 例えば、「GROUP BY 部門コード」なのに、SELECT句に社員名を書くことはできない(グループの中に何人もいるので1つに決まらない)
SQLで使える集合関数(★)
| 関数 | 意味 |
|---|---|
| SUM(列名) | 列の値の合計 |
| AVG(列名) | 列の値の平均 |
| MAX(列名) | 列の値の最大値 |
| MIN(列名) | 列の値の最小値 |
| COUNT(*) | 行の総数 |
| COUNT(列名) | 列の値がNULLでない行の総数 |
- 集合関数を使うときの注意:
- 列の値がNULLのものは除かれてから集計される
- カッコの中に、算術式やCASE式なども書ける
- 関数AVGの演算精度は、データベース製品による
例題(集合関数とNULL)
- 問題:
- 列Xの値が、10、20、NULL、30 の4行の表がある。COUNT(*)、COUNT(X)、SUM(X)、AVG(X)はそれぞれいくつか
- 答え:
- COUNT(*)は、行を全部数えるので 4
- COUNT(X)は、NULLを除くので 3
- SUM(X)は、10 + 20 + 30 = 60
- AVG(X)は、NULLを除いた3行の平均で、60 ÷ 3 = 20
- ひっかけ注意:
- AVG(X)を「60 ÷ 4 = 15」と計算するのは誤り。NULLは0ではなく、計算から外れる
- 検算:
- AVG(X) = SUM(X) ÷ COUNT(X) = 60 ÷ 3 = 20 で一致
⑦ 出力順の指定(ORDER BY)
- ORDER BY句:
- 問合せ結果を、ある列の値で昇順(ASC)あるいは降順(DESC)に並べ替える
- ORDER BYの後に、並べ替えの基になる列名と、並べ替えの順を書く
- 書き方の例:
- 年齢の降順なら「ORDER BY 年齢 DESC」
- 年齢の降順、社員コードの昇順なら「ORDER BY 年齢 DESC, 社員コード ASC」
- ASCは省略できる:
- 省略した場合はASC(昇順)とみなされる
- 例:
- 「SELECT 社員名, 年齢 FROM 社員 ORDER BY 年齢 DESC」の結果は、岡本恵(30)、小林誠(28)、石井健(24)、青木進(22)、青木花子(19)
- 覚え方:
- ASCはascending(上がっていく=小さい順)、DESCはdescending(下がっていく=大きい順)
混同しやすいペア
- DDL / DML
- DDLは、データ定義言語(CREATE、DROP、ALTER)
- DMLは、データ操作言語(SELECT、INSERT、UPDATE、DELETE)
- DROP / DELETE
- DROPは、表などのデータベースオブジェクトそのものを削除する
- DELETEは、表の中の行を削除する(全行消しても表は残る)
- GRANT / REVOKE
- GRANTは、アクセス権を付与する
- REVOKEは、アクセス権を取り消す
- COMMIT / ROLLBACK
- COMMITは、トランザクションの更新処理を確定する
- ROLLBACKは、トランザクションの更新処理を取り消す
- WHERE句 / HAVING句
- WHERE句は、グループ化の前に、行を選ぶ
- HAVING句は、グループ化の後に、グループを選ぶ(集合関数が使える)
- DISTINCT / ALL
- DISTINCTは、重複行を取り除く
- ALLは、重複行も含める(省略時はALL)
- 「= NULL」 / 「IS NULL」
- 「= NULL」は、比較の結果が不定になるので使えない
- 「IS NULL」で、NULLかどうかを判定する
- BETWEEN / IN
- BETWEENは、範囲(値1〜値2、両端を含む)に入るか
- INは、値リストのどれかと等しいか
- %(LIKE) / _(LIKE)
- %は、0文字以上の任意の文字列
- _は、任意の1文字
- COUNT(*) / COUNT(列名)
- COUNT(*)は、行の総数(NULLの行も数える)
- COUNT(列名)は、その列がNULLでない行の数
- ASC / DESC
- ASCは、昇順(小さい順)。省略時はこれ
- DESCは、降順(大きい順)