SQLの中で、最も基本でありながら奥が深いのが「SELECT文」です。
この記事では、Accessで使えるSELECT文の基本から、集計やサブクエリなどの応用テクニックまでを一通り解説します。これから学びたい方も、もう一度基礎をおさらいしたい方も、ぜひご覧ください。
なお、Accessではデータ抽出「クエリ」を用いることが多いですが、こちらの記事では、クエリとSQLの関係性について解説していますので、併せてご覧いただければと思います。
SELECT文の基本構文
一番シンプルなパターン
SELECT フィールド名 FROM テーブル名;
こちらが最も、シンプルなSELECT文の基本形です。構文の意味は以下のとおりです。
SELECT句…抽出するフィールドを指定する部分FROM句…どのテーブルやクエリを対象にするかを指定
複数フィールドを抽出するパターン
SELECT 社員コード,社員名 FROM M_社員基本情報マスタ;
複数のフィールドを抽出する場合はSELECT句に,(カンマ)で区切ったフィールドをつなげていきます。
《抽出結果》

フィールドに別名を付けるパターン(As句による別名指定)
SELECT 社員コード AS 社員Code, 社員名 AS 社員名_姓のみ FROM M_社員基本情報マスタ;
As句を用いることで、実際のフィールド名を変更して抽出結果を表示することができます。使い方は、SELECT句に指定したフィールドの後ろにAsを挿入し、その後に別名を指定します。各句とフィールドの間には半角スペースを入れます。
テーブル同士をJOINする複雑なSQLの場合、テーブル名を「T1」「T2」といった感じで簡略化する使用方法もよく見られます。
《抽出結果》

データを絞り込むパターン(WHERE句)
SELECT 社員コード,社員名,基本給与 FROM M_社員基本情報マスタ WHERE 基本給与 >= 300000;
条件を指定してデータを絞り込む場合はWHERE句を使います。
《抽出結果》

事例では比較演算子である>=を使い、基本給与が30万円以上の社員を抽出しています。条件指定方法には、下記のような様々な方法があります。
- 比較演算子:
=,<>,<,>,>=,<= - 範囲指定:
BETWEEN 10 AND 20 - 候補指定:
IN("営業部", "開発部") - パターンマッチング:
LIKE "田中*" - NUllチェック:
IS NULL,IS NOT NULL
データを並び替えるパターン(ORDER BY句)
SELECT 社員コード,社員名,生年月日 FROM M_社員基本情報マスタ ORDER BY 生年月日 DESC;
あるフィールドを基準にしてデータを並び替える場合は、ORDER BY句を使用します。
《抽出結果》

事例では「生年月日」フィールドを降順に並び替えるパターンです。なお、並び替えには「昇順」と「降順」があります。また、優先順位をつけて複数のフィールドを並び替えることも可能です。その場合はORDER BY句の後に,(カンマ)で区切ったフィールドをつなげていきます。
- ASC:昇順(省略可能)
- DESC:降順
SELECT文の応用構文
計算列を追加するパターン(集計関数等の使用)
SELECT 社員コード,社員名,基本給与,基本給与*1.05 As 昇給後の給与 FROM M_社員基本情報マスタ;
既存のフィールドを元に計算を行い、新たなフィールドとして表示することができます。
《抽出結果》

事例では、「基本給与」フィールドに一律5%を加算し、「昇給後の給与」というフィールドを新たに作成しています。
上記のような計算方法もあれば、下記のように関数を使う場合もあります。
SELECT 社員コード,社員名,生年月日,DateDiff("yyyy",[生年月日],date())&"歳" As 年齢
FROM M_社員基本情報マスタ;
《抽出結果》

事例では、DateDiff関数を使って「生年月日」フィールドから現在の年齢を求めるパターンです。ここでも「年齢」という新たなフィールドを作成しています。

この事例では簡略化しましたが、DateDiff関数での年齢算出は、年が超えると1歳加算されるため、正確な年齢を導き出すにはIFF文による判断式が必要です。
グループごとに集計するパターン(GROUP BY句)
SELECT 所属名, AVG(基本給与) AS 平均給与額
FROM SQ_社員情報閲覧
GROUP BY 所属名;
あるフィールドを基準にしてグループ化して、集計や平均等を求める場合は、GROUP BY句を使用します。

事例では、「所属名」フィールドをグループ化し、AVG関数により部署ごとの「基本給与」平均額を求めています。このようなグループ時に使用する関数には、下記のようなものがあります。
- COUNT関数:件数を求める
- SUM関数:合計する
- MAX関数:最大値を求める
- MIN関数:最小値を求める
グループ化後の条件指定による絞り込み(HAVING句)
SELECT 所属名, AVG(基本給与) AS 平均給与額
FROM SQ_社員情報閲覧
GROUP BY 所属名;
HAVING AVG(基本給与)>300000;
グループ化した後のデータに対して、条件指定によるデータ絞り込みを行うにはHAVING句を使用します。
《抽出結果》

事例は、所属部署ごとの平均給与額について、30万円以上の部署のみ抽出したパターンです。
上位から任意の順位を抽出するパターン(TOP句)
SELECT TOP 5 社員名,基本給与 FROM M_社員基本情報マスタ ORDER BY 基本給与 DESC;
TOP句は、SELECT文で取得するレコード数を制限するための構文です。「上位○件だけ表示したい」といった場面で使うことができます。
《抽出結果》

事例では、基本給与が高い順にトップ5を抽出する例です。ORDER BY句を組み合わせることで、上位を判断しています。
重複データを排除するパターン(DISTINCT句)
SELECT DISTINCT 所属名 FROM SQ_社員情報閲覧;
単純に重複しているレコードを1つにまとめて表示したい場合は、DISTINCT句を使用します。
《抽出結果》

事例は、所属名の重複を排除して表示しているパターンです。
テーブル接続後に条件指定による絞り込み(JOIN句)
SELECT M_社員基本情報マスタ.社員名, M_所属マスタ.所属名
FROM M_社員基本情報マスタ
INNER JOIN M_所属マスタ ON M_社員基本情報マスタ.所属コード = M_所属マスタ.所属コード
WHERE M_所属マスタ.所属名 = "営業部";
テーブル同士をJOIN句でつなげたうえで、WHERE句による条件指定を行っているパターンです。
《抽出結果》

事例では、「M_社員基本情報マスタ」と「M_所属マスタ」の2つのテーブルを、両テーブルに共通する「所属コード」フィールドにより接続し、1つのテーブルと見なしています。そのうえでWHERE句を使い、所属部署が営業部の社員のみを抽出しています。
事例で使っているINNER JOINは、両テーブルで所属コードが合致するもののみ抽出するものとなっています。JOIN句にはこのほかに、LEFT JOIN、RIGHT JOINがあり、片方のテーブルに所属コードの値が存在しないレコードも抽出することができます。
サブクエリを使用したパターン
SELECT 社員コード,社員名 FROM M_社員基本情報マスタ
WHERE 役職コード
IN (SELECT 役職コード FROM M_役職マスタ WHERE 役職名 = '係長');
サブクエリとは、SELECT文のWHERE句に、別のSELECT文を内部に含めたSQLのことで、「副問合せ」ともよびます。
《抽出結果》

事例では、IN句の中のSELECT文で「M_役職マスタ」テーブルの「役職名」フィールドから「係長」に合致するレコードを抽出しています。このSELECT文で抽出しているデータは「役職コード」であり、この値が最初のSELECT文のWHERE句の役職コードと合致するかどうか反映されます。
なお、サブクエリの抽出条件が1つだけであれば、比較演算子が=(イコール)で構いませんが、例えば「部長」「係長」と2つ以上の条件であれば、IN句を使用する必要があります。
また、別のテーブルとつなげる点では、前述したJOINパターンと似ていますが、JOINの場合は2つのテーブルを統合して、1つのテーブルに見なすことに対して、サブクエリはあくまで条件指定の一部として機能します。よって、サブクエリのSELECT文で抽出したデータは表示されません。
参考までに、サブクエリはクエリでも使用することができます。今回の事例をクエリのデザインビューで表示すると以下のとおりとなります。

まとめ
最後に、SELECT文の主要要素をすべて網羅した構文としてまとめます。
| SELECT文構成内容 | 内容 | 必須 |
|---|---|---|
| SELECT | 列1、列2… | 必須 |
| FROM | 表1(JOINで表2、表3…) | 必須 |
| WHERE | 列に対する条件 | – |
| GROUP BY | 列1、列2… | – |
| HAVING | グループに対する条件 | – |
| ORDER BY | 列1、列2… | – |
《実例》
SELECT M_所属マスタ.所属名,SUM(T_営業実績.売上金額) AS 合計売上
FROM (M_社員基本情報マスタ
INNER JOIN T_営業実績 ON M_社員基本情報マスタ.社員コード = T_営業実績.社員コード)
INNER JOIN M_所属マスタ ON M_社員基本情報マスタ.所属コード = M_所属マスタ.所属コード
WHERE T_営業実績.売上日 BETWEEN #2025/01/01# AND #2025/01/30#
GROUP BY M_所属マスタ.所属名
HAVING SUM(T_営業実績.売上金額) >= 50000
ORDER BY 合計売上 DESC;
参考までに、こちらのSELECT文をクエリのデザインビューで表示すると、以下のとおりとなります。




