SQLの句(SQL clauses)

分類
テクノロジ系 データベース
出る試験
基本情報応用情報
重要度
★★★★★

SELECT文を組み立てる部品。書く順番と、実際に処理される順番が違うため、WHEREとHAVINGの使い分けが問われる。

もう少し詳しい説明

SQLは関係データベースを操作する言語です。中心になるのが、データを取り出すSELECT文です。

SELECT文は、句と呼ばれる部品を決まった順に並べて作ります。

このページで使う表

句の説明では、何を書くと何が出てくるのかを毎回この表で見ていきます。店ごとの売上を1件ずつ記録した売上明細という表です。

店コード店名都道府県売上
S01新宿店東京都600000
S01新宿店東京都500000
S02渋谷店東京都400000
S02渋谷店東京都300000
S03横浜店神奈川県900000
S03横浜店神奈川県800000

1行が1件の売上です。同じ店が何度も出てきます。

書く順番

SELECT   列名
FROM     表名
WHERE    行の条件
GROUP BY まとめる基準の列
HAVING   まとめたあとの条件
ORDER BY 並べ替えの基準
句何をするか
SELECTどの列を出すか
FROMどの表から取るか
WHEREどの行を残すか
GROUP BYどの列が同じ行を1つにまとめるか
HAVINGまとめたあとの条件
ORDER BY結果をどの順に並べるか

この順番どおりに書かないと、文として成り立ちません。

1つずつ、何が出るのかを見る

SELECT と FROM だけなら、指定した列がそのまま全部出ます。

SELECT 店名, 売上
FROM   売上明細
店名売上
新宿店600000
新宿店500000
渋谷店400000
渋谷店300000
横浜店900000
横浜店800000

6行のまま、列だけが2つに減りました。SELECT は列を選び、行は減らしません。

WHERE を足すと、行が減ります。

SELECT 店名, 売上
FROM   売上明細
WHERE  都道府県 = '東京都'
店名売上
新宿店600000
新宿店500000
渋谷店400000
渋谷店300000

神奈川県の2行が消えました。 WHERE は、1行ずつ見て、条件に合わない行を落とします。

GROUP BY を足すと、行がまとまります。

SELECT 店コード, SUM(売上)
FROM   売上明細
GROUP BY 店コード
店コードSUM(売上)
S011100000
S02700000
S031700000

6行が3行になりました。 同じ店コードの行が1つにまとめられ、SUM(売上) がその店の合計になっています。まとめたあとは、1行が1つの店を表します。

ORDER BY を足すと、並び順が変わります。

SELECT 店コード, SUM(売上)
FROM   売上明細
GROUP BY 店コード
ORDER BY SUM(売上) DESC
店コードSUM(売上)
S031700000
S011100000
S02700000

行の数も中身も変わらず、並びだけが入れ替わりました。 DESC は大きいほうが先、という指定です。

書く順番と、処理される順番が違う

試験で問われるのは、ここです。

書く順番SELECTFROMWHEREGROUP BYHAVINGORDER BY処理の順番FROMWHEREGROUP BYHAVINGSELECTORDER BY
上の段が書く順番、下の段が処理される順番です。色を付けたSELECTの位置が違います。先頭に書くのに、処理されるのは終わりのほうだ、ということです。ここから2つのことが決まります。1つは、WHEREがGROUP BYより先に動くので、WHEREの時点ではまだ合計が出ておらず、集計関数を書けないこと。もう1つは、SELECTで付けた別名を、あとに動くORDER BYでは使えて、先に動くWHEREでは使えないことです。
順番
書く順番SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY
処理される順番FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY

SELECTは、いちばん先に書くのに、処理されるのはほぼ最後です。

この食い違いから、2つのことが決まります。

1. WHEREに集計関数を書けない。

WHERE が動くのは GROUP BY より前です。前の節で見たとおり、GROUP BY でまとめて初めて合計が出ます。WHERE の時点では、まだ1行ずつバラバラの状態で、合計という値がどこにも存在しません。

SELECT 店コード, SUM(売上)
FROM   売上明細
WHERE  SUM(売上) > 1000000   ← これは書けない
GROUP BY 店コード

無いものと比べることはできないので、文として成り立ちません。

2. SELECTで付けた別名は、ORDER BYでは使えて、WHEREでは使えない。

AS を使うと、列に別の名前を付けられます。

SELECT 店コード, SUM(売上) AS 合計
FROM   売上明細
GROUP BY 店コード
ORDER BY 合計 DESC   ← 使える

ORDER BY が動くのは SELECT のあとなので、そのときには「合計」という名前がもう付いています。

SELECT 店コード, SUM(売上) AS 合計
FROM   売上明細
WHERE  合計 > 1000000   ← 使えない
GROUP BY 店コード

WHERE が動くのは SELECT の前です。その時点では「合計」という名前はまだ付いていません。

どちらも、順番の1本から出てきます。 別々に覚えようとすると、どちらがどちらか毎回迷います。

WHEREとHAVINGの使い分け

いつ効くか何に対する条件か
WHEREまとめる前1行ずつ
HAVINGまとめたあとグループごとの集計値

たとえば「東京都の店だけを対象に、売上合計が100万円を超える店を出す」なら、こうなります。

SELECT 店コード, SUM(売上) AS 合計
FROM   売上明細
WHERE  都道府県 = '東京都'
GROUP BY 店コード
HAVING SUM(売上) > 1000000

この文が、どう動くのかを順に追います。

① FROM … 売上明細の6行を取り出します。

店コード店名都道府県売上
S01新宿店東京都600000
S01新宿店東京都500000
S02渋谷店東京都400000
S02渋谷店東京都300000
S03横浜店神奈川県900000
S03横浜店神奈川県800000

② WHERE … 1行ずつ見て、都道府県が東京都でない行を落とします。

店コード店名都道府県売上
S01新宿店東京都600000
S01新宿店東京都500000
S02渋谷店東京都400000
S02渋谷店東京都300000

ここで横浜店が消えます。 合計すれば170万円で、いちばん大きい店です。それでも先に落ちているので、このあとの計算には出てきません。

③ GROUP BY … 店コードが同じ行を1つにまとめ、売上を合計します。

店コード合計
S011100000
S02700000

④ HAVING … まとまった行を見て、合計が100万円を超えないものを落とします。

店コード合計
S011100000

⑤ SELECT … 指定された列(店コードと合計)を出します。これが答えです。

店コード合計
S011100000

都道府県の条件はWHERE(1行ずつで判断できる)、合計の条件はHAVING(まとめないと分からない)です。

この2つを入れ替えると、答えが変わります。 WHERE を外して HAVING だけにすると、横浜店が落ちないまま③へ進むので、S03(170万円)とS01(110万円)の2行が出ます。試験では、ここを入れ替えた選択肢が並びます。

集計関数

GROUP BYと組にして使います。

関数何を出すかNULLの扱い
COUNT(*)行数NULLの行も数える
COUNT(列名)その列がNULLでない行数NULLは数えない
SUM(列名)合計NULLは無視
AVG(列名)平均NULLは無視(分母にも入らない)
MAX / MIN最大・最小NULLは無視

COUNT(*) と COUNT(列名) の違いは、そのまま出題されます。

AVGでも同じことが起きます。NULLの行は分母にも入りません。5行のうち2行がNULLなら、3で割った値が出ます。0として扱って5で割るわけではありません。

重複を消す

DISTINCT を付けると、同じ値が1つにまとめられます。

SELECT DISTINCT 店コード
FROM   売上明細
店コード
S01
S02
S03

DISTINCT を付けないと、売上明細の6行ぶんがそのまま出ます(S01が2行、S02が2行、S03が2行)。

SELECTは、何もしなければ重複を消しません。 消したいときだけ DISTINCT を付けます。これも取り違えやすいところです。

並べ替え

ORDER BY は、既定で昇順(小さいほうが先)です。

書き方並び
ORDER BY 売上昇順(ASC を省いた形)
ORDER BY 売上 DESC降順
ORDER BY 部署, 売上 DESC部署で昇順、同じ部署の中で売上の降順

列を2つ書いたときは、左が優先です。

表をつなぐ

複数の表から取り出すときは、つなぎ目の列を指定します。

SELECT 社員.氏名, 部署.部署名
FROM   社員 JOIN 部署 ON 社員.部署コード = 部署.部署コード

ON に書くのがつなぎ目、WHERE に書くのが絞り込みです。役割が違うので、分けて書きます。

この2つの表があるとします。

社員表

社員番号氏名部署コード
1001佐藤D01
1002鈴木D02
1003田中(空)

部署表

部署コード部署名
D01営業部
D02開発部

田中には部署コードが入っていません。異動の途中など、つなぎ先がない行です。

つなぎ先がない行をどう扱うかで、結合の種類が分かれます。

書き方つなぎ先がない行
INNER JOIN(内部結合)消える
LEFT OUTER JOIN(左外部結合)左の表の行は残り、右側がNULLになる

INNER JOIN で結んだ結果です。

氏名部署名
佐藤営業部
鈴木開発部

田中が消えました。 部署表につなぎ先が無いためです。

LEFT OUTER JOIN で結んだ結果です。

氏名部署名
佐藤営業部
鈴木開発部
田中NULL

田中が残り、部署名のところがNULL(値が入っていない状態)になります。 部署に所属していない社員も一覧に出したいなら、こちらを使います。内部結合では消えてしまいます。

試験ではこう出る

科目A(旧・午前)でいちばん多いのが、WHEREとHAVINGの使い分けです。「グループ化した結果に条件を付ける」と書いてあればHAVINGです。

次が、与えられたSELECT文の実行結果を答える形です。小さな表が示され、結果の行数や値を選びます。処理の順番(FROM→WHERE→GROUP BY→HAVING→SELECT→ORDER BY)で追うと間違えません。

COUNT(*) と COUNT(列名) の差、NULLを含む列のAVGも繰り返し出ます。

応用情報では、結合を含む問合せの読み取りと、内部結合と外部結合で結果の行数が変わることが問われます。

関連する用語

関係データベース
SQLはこれを操作する言語。表から表を作る
実表と導出表
SELECT文に名前を付けたものがビュー
主キー
表を結合するとき、つなぎ目になる列
インデックス
WHEREで絞る列に付けると検索が速くなる

ミニクイズ

SQLで、グループごとに集計した結果に対して条件を付けたい。使う句として適切なものはどれか。

正解は 1番:HAVING句

集計したあとの結果に条件を付けるのはHAVING句です。WHERE句はグループにまとめる前の、1行ずつに対して条件を付けます。処理の順番がWHERE→GROUP BY→HAVINGなので、WHEREの時点ではまだ合計が出ていません。そのためWHEREにSUMやCOUNTを書くことはできません。GROUP BY句はまとめる基準になる列を指定する句、ORDER BY句は結果の並び順を決める句で、どちらも条件を付ける句ではありません。

間違えた用語の復習リストを見る →

この分野をまとめて解く → データベースのミニテスト(全35問)

最終更新:2026-10-20