この章で得られるスキル:
- ✅ SELECT文でテーブルからデータを取得できる
- ✅ 特定の列だけを取得できる
- ✅ 列名に別名(エイリアス)を付けられる
- ✅ 計算式を使った列を作成できる
- ✅ DISTINCTで重複を除去できる
- ✅ LIMITで取得件数を制限できる
Step 0: まず体験してみよう
シナリオ:大量のデータから必要な情報だけを取り出したい
以下のSQLを実行してみよう。 SELECT * で全データが表示される。
CREATE TABLE departments (
dept_id INTEGER PRIMARY KEY,
dept_name VARCHAR(50) NOT NULL UNIQUE,
location VARCHAR(50)
);
CREATE TABLE employees (
emp_id INTEGER PRIMARY KEY,
emp_name VARCHAR(50) NOT NULL,
dept_id INTEGER REFERENCES departments(dept_id),
hire_date DATE NOT NULL,
salary INTEGER CHECK (salary > 0),
email VARCHAR(100) UNIQUE
);
INSERT INTO departments VALUES (1, '営業部', '東京');
INSERT INTO departments VALUES (2, '開発部', '大阪');
INSERT INTO departments VALUES (3, '人事部', '東京');
INSERT INTO employees VALUES (1, '田中太郎', 1, '2020-04-01', 350000, 'tanaka@example.com');
INSERT INTO employees VALUES (2, '佐藤花子', 2, '2021-04-01', 400000, 'sato@example.com');
INSERT INTO employees VALUES (3, '鈴木一郎', 2, '2022-04-01', 320000, 'suzuki@example.com');
INSERT INTO employees VALUES (4, '高橋美咲', 3, '2023-04-01', 280000, 'takahashi@example.com');
INSERT INTO employees VALUES (5, '伊藤健太', 1, '2021-10-01', 330000, 'ito@example.com');
INSERT INTO employees VALUES (6, '渡辺あかり', 2, '2023-07-01', 300000, 'watanabe@example.com');
-- 全データを取得
SELECT * FROM employees;
全ての列が表示されるが、名前とメールアドレスだけ知りたい場合は?
部門の一覧を見たいが、重複した部門名が何度も出る場合は?
この章では、 必要なデータだけを効率的に取り出す方法 を学ぶ。
Step 1: SELECT文の基本
SELECT文の基本構文
データを取得するには SELECT 文を使う。SQLの中で 最も頻繁に使う 命令である。
SELECT * FROM テーブル名;
SELECT 列名1, 列名2 FROM テーブル名;
| 要素 | 意味 |
|---|
SELECT | 「取得する」という命令 |
* | 全ての列 |
FROM | 「〜から」 |
; | SQL文の終わり |
CREATE TABLE departments (
dept_id INTEGER PRIMARY KEY,
dept_name VARCHAR(50) NOT NULL UNIQUE,
location VARCHAR(50)
);
INSERT INTO departments VALUES (1, '営業部', '東京');
INSERT INTO departments VALUES (2, '開発部', '大阪');
INSERT INTO departments VALUES (3, '人事部', '東京');
-- テーブルの全データを取得
SELECT * FROM departments;
SELECT * は手軽だが、不要な列まで取得するためパフォーマンスが悪くなる場合がある。
実務では 必要な列だけを指定する のが基本である。
Step 2: 列の指定
特定の列だけを取得する
SELECT の後に列名をカンマ区切りで指定すると、その列だけを取得できる。
CREATE TABLE employees (
emp_id INTEGER PRIMARY KEY,
emp_name VARCHAR(50) NOT NULL,
dept_id INTEGER,
hire_date DATE NOT NULL,
salary INTEGER,
email VARCHAR(100)
);
INSERT INTO employees VALUES (1, '田中太郎', 1, '2020-04-01', 350000, 'tanaka@example.com');
INSERT INTO employees VALUES (2, '佐藤花子', 2, '2021-04-01', 400000, 'sato@example.com');
INSERT INTO employees VALUES (3, '鈴木一郎', 2, '2022-04-01', 320000, 'suzuki@example.com');
INSERT INTO employees VALUES (4, '高橋美咲', 3, '2023-04-01', 280000, 'takahashi@example.com');
-- 名前とメールアドレスだけ取得
SELECT emp_name, email FROM employees;
-- 列の順序を自由に指定できる
SELECT email, emp_name, salary FROM employees;
やってみよう
上のコードを変更して、以下を試してみよう。
emp_name と salary だけを取得する
hire_date と emp_name の順序で取得する
Step 3: 列の別名(AS)
AS句で列名に別名を付ける
取得結果の列名を、わかりやすい名前に変更できる。
SELECT 列名 AS 別名 FROM テーブル名;
CREATE TABLE employees (
emp_id INTEGER PRIMARY KEY,
emp_name VARCHAR(50) NOT NULL,
salary INTEGER,
hire_date DATE NOT NULL
);
INSERT INTO employees VALUES (1, '田中太郎', 350000, '2020-04-01');
INSERT INTO employees VALUES (2, '佐藤花子', 400000, '2021-04-01');
INSERT INTO employees VALUES (3, '鈴木一郎', 320000, '2022-04-01');
-- 列に別名を付ける
SELECT
emp_name AS 社員名,
salary AS 月給,
hire_date AS 入社日
FROM employees;
別名の用途
| 用途 | 例 |
|---|
| 日本語で表示したい | emp_name AS 社員名 |
| 計算結果にわかりやすい名前を付けたい | salary * 12 AS 年収 |
| 長い列名を短くしたい | department_name AS dept |
AS は省略することもできる(SELECT emp_name 社員名 FROM employees;)。
ただし、読みやすさのために AS を書くことが推奨される。
Step 4: 式を使った列の作成
計算式を使う
SELECT句では、列の値を使った 計算式 を書ける。
CREATE TABLE employees (
emp_id INTEGER PRIMARY KEY,
emp_name VARCHAR(50) NOT NULL,
salary INTEGER
);
INSERT INTO employees VALUES (1, '田中太郎', 350000);
INSERT INTO employees VALUES (2, '佐藤花子', 400000);
INSERT INTO employees VALUES (3, '鈴木一郎', 320000);
-- 月給から年収を計算
SELECT emp_name, salary AS 月給, salary * 12 AS 年収 FROM employees;
-- 手取り(税引き後)を概算
SELECT emp_name, salary, salary * 0.8 AS 手取り概算 FROM employees;
文字列の連結
PostgreSQLでは || 演算子で文字列を連結できる。
CREATE TABLE employees (
emp_id INTEGER PRIMARY KEY,
emp_name VARCHAR(50) NOT NULL,
email VARCHAR(100)
);
INSERT INTO employees VALUES (1, '田中太郎', 'tanaka@example.com');
INSERT INTO employees VALUES (2, '佐藤花子', 'sato@example.com');
-- 文字列を連結
SELECT emp_name || '(' || email || ')' AS 社員情報 FROM employees;
NULLと計算
NULLを含む計算の結果は すべてNULL になる。
SELECT salary + bonus AS 総支給 FROM employees;
NULLを0として扱いたい場合は COALESCE 関数を使う。
SELECT salary + COALESCE(bonus, 0) AS 総支給 FROM employees;
Step 5: 重複の除去(DISTINCT)
DISTINCTで重複を除去する
DISTINCT を付けると、結果から 重複する行を除去 できる。
CREATE TABLE departments (
dept_id INTEGER PRIMARY KEY,
dept_name VARCHAR(50) NOT NULL UNIQUE,
location VARCHAR(50)
);
CREATE TABLE employees (
emp_id INTEGER PRIMARY KEY,
emp_name VARCHAR(50) NOT NULL,
dept_id INTEGER REFERENCES departments(dept_id),
hire_date DATE NOT NULL
);
INSERT INTO departments VALUES (1, '営業部', '東京');
INSERT INTO departments VALUES (2, '開発部', '大阪');
INSERT INTO departments VALUES (3, '人事部', '東京');
INSERT INTO employees VALUES (1, '田中太郎', 1, '2020-04-01');
INSERT INTO employees VALUES (2, '佐藤花子', 2, '2021-04-01');
INSERT INTO employees VALUES (3, '鈴木一郎', 2, '2022-04-01');
INSERT INTO employees VALUES (4, '高橋美咲', 3, '2023-04-01');
INSERT INTO employees VALUES (5, '伊藤健太', 1, '2021-10-01');
-- 重複あり:dept_idが2回出る
SELECT dept_id FROM employees;
-- 重複除去:ユニークなdept_idだけ取得
SELECT DISTINCT dept_id FROM employees;
-- 勤務地の一覧(重複除去)
SELECT DISTINCT location FROM departments;
複数列に対するDISTINCT
DISTINCT は 行全体 で重複を判定する。
SELECT DISTINCT dept_id, location FROM ...;
Step 6: 取得件数の制限(LIMIT)
LIMITで最初のN件だけ取得する
LIMIT を使うと、取得する行数を制限できる。
SELECT * FROM テーブル名 LIMIT 件数;
CREATE TABLE employees (
emp_id INTEGER PRIMARY KEY,
emp_name VARCHAR(50) NOT NULL,
salary INTEGER,
hire_date DATE NOT NULL
);
INSERT INTO employees VALUES (1, '田中太郎', 350000, '2020-04-01');
INSERT INTO employees VALUES (2, '佐藤花子', 400000, '2021-04-01');
INSERT INTO employees VALUES (3, '鈴木一郎', 320000, '2022-04-01');
INSERT INTO employees VALUES (4, '高橋美咲', 280000, '2023-04-01');
INSERT INTO employees VALUES (5, '伊藤健太', 330000, '2021-10-01');
INSERT INTO employees VALUES (6, '渡辺あかり', 300000, '2023-07-01');
-- 最初の3件だけ取得
SELECT * FROM employees LIMIT 3;
-- OFFSETで開始位置を指定(3件目から2件取得)
SELECT * FROM employees LIMIT 2 OFFSET 3;
OFFSET(開始位置の指定)
OFFSET を使うと、先頭から指定した行数を飛ばしてからデータを取得できる。
Webアプリの ページネーション でよく使われる。
| 構文 | 意味 |
|---|
LIMIT 10 | 最初の10件を取得 |
LIMIT 10 OFFSET 0 | 1ページ目(1〜10件目) |
LIMIT 10 OFFSET 10 | 2ページ目(11〜20件目) |
LIMIT 10 OFFSET 20 | 3ページ目(21〜30件目) |
Webアプリで「次のページ」をクリックすると、裏側ではOFFSETの値が変わったSQLが実行されている。
Spring + MyBatisでリスト画面を作る際にも、LIMITとOFFSETを使ったページネーションは必須の知識である。
Step 7: AI活用のポイント
AIにSELECT文を書かせてみよう
ここまで学んだ知識があれば、AIに対して的確な指示を出せるようになる。
例1: 基本的なSELECT
「社員テーブルから名前とメールアドレスを取得するSQLを書いて」
AIの回答:
SELECT emp_name, email FROM employees;
例2: 計算式を含むSELECT
「社員テーブルから名前と年収(月給×12)を取得するSQLを書いて」
AIの回答:
SELECT emp_name, salary * 12 AS annual_salary FROM employees;
レビューのポイント
AIが生成したSQLを確認する際は、以下をチェックしよう。
| チェック項目 | 確認内容 |
|---|
| 列名は正しいか | テーブル定義と一致しているか |
| 別名はわかりやすいか | 結果を見て意味が通じるか |
| 不要な列が含まれていないか | SELECT * になっていないか |
| LIMITは適切か | 大量データの場合、件数制限があるか |
Step 8: 実践課題
課題1:部門の一覧を取得しよう
部門テーブルから 重複のない 所在地の一覧を取得するSQLを書いてみよう。
課題2:社員情報を見やすく表示しよう
社員テーブルから、以下の形式でデータを取得するSQLを書いてみよう。
- 社員名(「社員名」という別名)
- 月給(「月給」という別名)
- 年収(月給×12、「年収」という別名)
CREATE TABLE departments (
dept_id INTEGER PRIMARY KEY,
dept_name VARCHAR(50) NOT NULL UNIQUE,
location VARCHAR(50)
);
CREATE TABLE employees (
emp_id INTEGER PRIMARY KEY,
emp_name VARCHAR(50) NOT NULL,
dept_id INTEGER REFERENCES departments(dept_id),
hire_date DATE NOT NULL,
salary INTEGER CHECK (salary > 0),
email VARCHAR(100) UNIQUE
);
INSERT INTO departments VALUES (1, '営業部', '東京');
INSERT INTO departments VALUES (2, '開発部', '大阪');
INSERT INTO departments VALUES (3, '人事部', '東京');
INSERT INTO employees VALUES (1, '田中太郎', 1, '2020-04-01', 350000, 'tanaka@example.com');
INSERT INTO employees VALUES (2, '佐藤花子', 2, '2021-04-01', 400000, 'sato@example.com');
INSERT INTO employees VALUES (3, '鈴木一郎', 2, '2022-04-01', 320000, 'suzuki@example.com');
INSERT INTO employees VALUES (4, '高橋美咲', 3, '2023-04-01', 280000, 'takahashi@example.com');
INSERT INTO employees VALUES (5, '伊藤健太', 1, '2021-10-01', 330000, 'ito@example.com');
INSERT INTO employees VALUES (6, '渡辺あかり', 2, '2023-07-01', 300000, 'watanabe@example.com');
-- ここにSQLを書こう
課題3:最初の3人だけ取得しよう
社員テーブルから名前と入社日だけを取得し、最初の3件だけ表示するSQLを書いてみよう。
まとめ
この章では、 SELECT文の基礎 を学んだ。
🎯 達成できたこと
- ✅ SELECT文でテーブルからデータを取得できるようになった
- ✅ 特定の列だけを取得できるようになった
- ✅ 列名に別名(エイリアス)を付けられるようになった
- ✅ 計算式を使った列を作成できるようになった
- ✅ DISTINCTで重複を除去できるようになった
- ✅ LIMITで取得件数を制限できるようになった
📚 学んだ内容
| 構文 | 意味 | 例 |
|---|
SELECT * | 全ての列を取得 | SELECT * FROM employees |
SELECT 列名 | 特定の列を取得 | SELECT emp_name, salary FROM employees |
AS | 列に別名を付ける | SELECT salary AS 月給 |
DISTINCT | 重複を除去する | SELECT DISTINCT dept_id FROM employees |
LIMIT | 取得件数を制限 | SELECT * FROM employees LIMIT 10 |
OFFSET | 開始位置を指定 | LIMIT 10 OFFSET 20 |
🚀 次のステップ
次の章では、 データの絞り込みと並び替え を学ぶ。
WHERE句で条件を指定し、ORDER BYで並び替える方法を理解しよう。
💡 よくある質問
Q1: SELECT * はなぜ使わないほうがよいのか?
A: SELECT * は全ての列を取得するため、不要な列のデータまで転送される。データ量が多い場合やネットワーク越しの通信ではパフォーマンスに影響する。また、テーブルに列が追加されたときに予期しない列が結果に含まれることもある。開発中の確認用としては便利だが、本番コードでは必要な列だけを指定するのが原則である。
Q2: LIMITなしで大量データを取得するとどうなるか?
A: テーブルに数百万件のデータがある場合、全件取得しようとするとメモリ不足やタイムアウトが発生する可能性がある。実務では必ず LIMIT を付けるか、WHERE句で条件を絞り込んで取得する。
Q3: ASで付けた別名は他の場所でも使えるか?
A: AS で付けた別名は、そのSELECT文の結果表示でのみ有効である。WHERE句やGROUP BY句では別名を使えない場合がある(PostgreSQLではORDER BY句では使える)。
Q4: DISTINCTとGROUP BYの違いは何か?
A: DISTINCT は単純に重複行を除去するだけである。 GROUP BY はグループ化して集計(COUNT、AVGなど)を行う際に使う。重複除去だけが目的なら DISTINCT 、集計を伴うなら GROUP BY を使う。GROUP BYについては第6章で学ぶ。
練習問題
この章の内容を理解できたか確認しよう。
- テーブル名・カラム名は 小文字 で入力する(例:
employees, dept_id)
- SQLキーワードは 大文字 で入力する(例:
SELECT, FROM, WHERE)
正しい例: SELECT emp_name FROM employees WHERE dept_id = 1;
departments テーブルの全データを取得するSQL文を完成させよ。
解答例
SELECT * FROM departments;
解説
SELECT * FROM テーブル名 はテーブルの全列・全行を取得する最も基本的なSQL文である。
基本構文:
SELECT * FROM テーブル名;
ポイント:
* はすべての列を意味するワイルドカード
FROM の後にテーブル名を指定する
- セミコロン
; でSQL文を終了する
- 実務では
SELECT * よりも必要な列だけを指定することが推奨される(パフォーマンス向上のため)
- テーブル名・カラム名は 小文字 で入力する(例:
employees, dept_id)
- SQLキーワードは 大文字 で入力する(例:
SELECT, FROM, WHERE)
正しい例: SELECT emp_name FROM employees WHERE dept_id = 1;
employees テーブルから emp_name と salary の列のみを取得するSQL文を完成させよ。
emp_name, salary
FROM employees;
解答例
SELECT emp_name, salary FROM employees;
解説
特定の列だけを取得するには SELECT 列名1, 列名2, ... のように列名をカンマ区切りで指定する。
基本構文:
SELECT 列名1, 列名2, ... FROM テーブル名;
ポイント:
- 列名はカンマ
, で区切る
- 列名の順序は取得結果の列の並び順になる
* の代わりに列名を列挙することで、必要なデータだけを効率的に取得できる
- ネットワーク転送量の削減やクエリの可読性向上のために、必要な列だけを指定するのが推奨される
- テーブル名・カラム名は 小文字 で入力する(例:
employees, dept_id)
- SQLキーワードは 大文字 で入力する(例:
SELECT, FROM, WHERE)
正しい例: SELECT emp_name FROM employees WHERE dept_id = 1;
emp_name を「社員名」、salary を「給与」という別名で取得するSQL文を完成させよ。
SELECT emp_name
社員名, salary
給与
FROM employees;
解答例
SELECT emp_name AS 社員名, salary AS 給与 FROM employees;
解説
AS キーワードで列に別名(エイリアス)を付けることができる。
基本構文:
SELECT 列名 AS 別名, ... FROM テーブル名;
ポイント:
- 日本語の別名も使用可能(スペースや特殊文字を含む場合は
" で囲む)
- 別名は取得結果の列ヘッダーに表示される
AS は省略可能(emp_name 社員名 と書いても同じ意味)だが、可読性のために付けることが推奨される
ORDER BY や HAVING では別名を使って参照できる
- テーブル名・カラム名は 小文字 で入力する(例:
employees, dept_id)
- SQLキーワードは 大文字 で入力する(例:
SELECT, FROM, WHERE)
正しい例: SELECT emp_name FROM employees WHERE dept_id = 1;
全社員の salary を12倍した「年収」を計算して取得するSQL文を完成させよ。
SELECT emp_name, salary *
年収
FROM employees;
解答例
SELECT emp_name, salary * 12 AS 年収 FROM employees;
解説
SELECT 句では列名だけでなく計算式も記述できる。
使用できる演算子:
+: 加算
-: 減算
*: 乗算
/: 除算
%: 剰余(余り)
ポイント:
- 計算式にも
AS で別名を付けることが推奨される
- データベースに保存されている値から動的に計算結果を取得できる
- 文字列の結合は
|| または CONCAT() 関数を使う
- テーブル名・カラム名は 小文字 で入力する(例:
employees, dept_id)
- SQLキーワードは 大文字 で入力する(例:
SELECT, FROM, WHERE)
正しい例: SELECT emp_name FROM employees WHERE dept_id = 1;
employees テーブルから dept_id の重複を除いた値一覧を取得するSQL文を完成させよ。
SELECT
dept_id
FROM employees;
解答例
SELECT DISTINCT dept_id FROM employees;
解説
DISTINCT キーワードを SELECT の直後に指定すると、重複する行を除いて結果を返す。
基本構文:
SELECT DISTINCT 列名 FROM テーブル名;
ポイント:
- どんな種類の値が存在するかを調べたいときに便利である
DISTINCT は SELECT の直後(列名の前)に1つだけ書く
- 複数列を指定した場合は、その組み合わせが重複しない行を返す
- 例:
SELECT DISTINCT dept_id, hire_date FROM employees → dept_idとhire_dateの組み合わせで重複除去
- テーブル名・カラム名は 小文字 で入力する(例:
employees, dept_id)
- SQLキーワードは 大文字 で入力する(例:
SELECT, FROM, WHERE)
正しい例: SELECT emp_name FROM employees WHERE dept_id = 1;
employees テーブルから最初の3件だけ取得するSQL文を完成させよ。
SELECT *
FROM employees
;
解答例
SELECT * FROM employees LIMIT 3;
解説
LIMIT n で取得する行数を制限できる。
基本構文:
SELECT * FROM テーブル名 LIMIT 件数;
ポイント:
- 大量のデータが存在するテーブルで先頭の数件だけ確認したいときに使用する
ORDER BY と組み合わせてランキングの上位N件を取得するときによく使う
OFFSET n を組み合わせるとn件をスキップしてから取得できる(ページング機能などに使用)
- 例:
LIMIT 10 OFFSET 20 → 21〜30件目を取得
DBMSによる違い:
- PostgreSQL・MySQL:
LIMIT n
- SQL Server:
SELECT TOP n ...
- Oracle:
WHERE ROWNUM <= n
以下のAIが生成したSQL文を見て、何を取得するSQL文かを正しく説明しているものを選べ。
SELECT emp_name, salary * 12 AS 年収
FROM employees
WHERE dept_id = 2
ORDER BY salary DESC
LIMIT 3;
正解
A. 開発部(dept_id=2)の社員を年収の高い順に上位3件取得する
解説
SQL文を各句に分けて読み解くと以下の通りである。
SELECT emp_name, salary * 12 AS 年収: 社員名と年収(月給×12)を取得
FROM employees: employeesテーブルから
WHERE dept_id = 2: 開発部(dept_id=2)に絞り込む
ORDER BY salary DESC: 給与の降順(高い順)に並べる
LIMIT 3: 上位3件に制限する
SQL文の読み方のコツ:
- まず
FROM で対象テーブルを確認する
WHERE で絞り込み条件を確認する
SELECT で取得する列と計算式を確認する
ORDER BY と LIMIT で並び順と件数制限を確認する
AIが生成したSQL文も、各句の意味を理解すれば正確に読み解くことができる。
- テーブル名・カラム名は 小文字 で入力する(例:
employees, dept_id)
- SQLキーワードは 大文字 で入力する(例:
SELECT, FROM, WHERE)
正しい例: SELECT emp_name FROM employees WHERE dept_id = 1;
「給与が350000以上の社員の emp_name と salary を取得せよ」という要件を満たすSQL文を完成させよ。
SELECT emp_name, salary
FROM employees
WHERE salary
;
解答例
SELECT emp_name, salary FROM employees WHERE salary >= 350000;
解説
要件を読んでSQL文に変換するときは、各条件を適切なSQL構文に対応させる。
比較演算子の対応:
- 「〜以上」→
>=
- 「〜以下」→
<=
- 「〜より大きい」→
>
- 「〜より小さい」→
<
- 「〜と等しい」→
=
- 「〜と等しくない」→
!= または <>
要件からSQL文への変換手順:
- 何のデータが必要か(SELECT句)
- どのテーブルから取得するか(FROM句)
- どんな条件で絞り込むか(WHERE句)
- 並び替えや件数制限が必要か(ORDER BY、LIMIT)