【初心者向け】SQL - SELECT文の基本構文と使い方を実例付きで解説

# 1. 【初心者向け】SQL - SELECT文の基本構文と使い方を実例付きで解説

 SQLの最も基本的な命令であるSELECT文に焦点を当て、データの取得方法を網羅的に解説します。

## 目次

- [はじめに](#はじめに)
- [基本的なデータ取得](#基本的なデータ取得)
  - [SELECT文の基本構文](#select文の基本構文)
  - [すべての列を取得する](#すべての列を取得する)
  - [特定の列を取得する](#特定の列を取得する)
  - [別名をつける](#別名をつける)
  - [重複を排除する](#重複を排除する)
- [条件を指定する（WHERE句）](#条件を指定するwhere句)
  - [比較演算子](#比較演算子)
  - [論理演算子](#論理演算子)
  - [BETWEEN](#between)
  - [IN / NOT IN](#in--not-in)
  - [IS NULL / IS NOT NULL](#is-null--is-not-null)
- [まとめ](#まとめ)
## はじめに

### プログラミング学習のきっかけとQiitaへの挑戦

皆様、こんにちは！

私は現在、仕事でVBAを使用するようになったことをきっかけにプログラミングに興味を持ち、独学でプログラミングの学習に励んでいます

より深く体系的にプログラミングを学ぶため、山浦清透さんの「独学エンジニア」を受講しており、その中でアウトプットの重要性を学びました。

そこで、日々の学習の成果を共有し、同じように独学で頑張る方々の少しでもお役に立てればと思い、Qiitaで技術記事を投稿していくことにしました。

今回のテーマは、Webアプリケーションや業務システムに不可欠な技術である「リレーショナルデータベース (RDB)」と、それを操作するための標準言語「SQL (Structured Query Language)」です。全4回の連載として、私が「独学エンジニア」で学んだ内容をベースに、以下の構成でまとめていきたいと思います。

1.  SQL - SELECT文の基本構文と使い方を実例付きで解説（本記事）
2.  データベースの正規化 - データの重複と矛盾をなくす
3.  SQLの実行計画 - クエリがどのように処理されるかを知る
4.  トランザクション - データの整合性を保証する仕組み

第1回となる本記事では、SQLの中でも最も基本的な命令であり、データ分析やアプリケーション開発において頻繁に使用される **SELECT文** に焦点を当て、その基礎的な内容を解説していきます。
***
### 用語の説明

理解を深めるために、まずはいくつかの重要な用語を確認しておきましょう。

 * **リレーションモデル:**
    * 現実世界のデータを、関連性を持つ複数の「リレーション（Relation）」という概念を使って表現するデータモデルです。
    * このリレーションは、一般的に「テーブル（Table）」と呼ばれる行と列から構成される二次元表として表現されます。
* **リレーショナルデータベース（RDB）:**
    * リレーションモデルに基づいてデータを管理するデータベースの種類のことを指します。
    * データの整合性や効率的な検索を実現するための様々な機能を提供します。
* **リレーショナルデータベース管理システム（RDBMS）:**
    * リレーショナルデータベースを操作・管理するため具体的に商品化したもの（ソフトウェア）です。
    * 代表的なRDBMSとしては、オープンソースの **MySQL** や **PostgreSQL**、商用の Oracle Database や Microsoft SQL Server などがあります。
* **SQL (Structured Query Language):**
    * リレーショナルデータベース管理システム (RDBMS) に対して、データの操作や定義を行うための標準的な言語です。
    * データの検索（SELECT）、挿入（INSERT）、更新（UPDATE）、削除（DELETE）といった操作や、テーブルの作成や変更などの定義を行うことができます。

---

![customersテーブルの構造とサンプルデータ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68011/975772b7-c915-462b-88ee-f2dce71343bb.png)





#### customersテーブル

下記のテーブルを使って解説していきます。

| id  | name             | age | created_at          |
| --- | ---------------- | --- | ------------------- |
| 1   | Taro Yamada      | 30  | 2025-05-03 06:11:10 |
| 2   | Misaki Kawasaki  | 25  | 2025-05-03 06:16:15 |
| 3   | Hiroshi Uchiyama | 25  | 2025-05-03 06:17:09 |
| 4   | Ai Tada          | 35  | 2025-05-03 10:59:43 |
| 5   | Mitsuo Kino      |     | 2025-05-03 11:20:57 |



## 基本的なデータ取得


### SELECT文の基本構文
#### `SELECT 列名 FROM テーブル名`

### すべての列を取得する

#### `SELECT * FROM テーブル名`

* **構文**
    * `SELECT *`: `*` (アスタリスク) は、テーブル内のすべての列を選択することを意味します。
    * `FROM テーブル名`: データを取得する対象のテーブルの名前を指定します。
    * `;`: SQL文の終端を示す記号です。

* **実行結果**
    * このクエリを実行すると、指定した テーブル名 に存在するすべてのデータが、行と列の形で結果セットとして返されます。列の順序は、通常テーブルが定義された際の列の順序になります。
* **注意点**
    * テーブルに大量のデータが含まれている場合、SELECT * を実行すると、非常に多くのデータが返ってくる可能性があり、パフォーマンスに影響を与えることがあります。必要な列だけを指定する方が効率的な場合が多いです。

##### 例：customersテーブルのすべての列を取得

```sql
 -- SELECT文のサンプル
SELECT * FROM customers;
```

##### 出力結果
```
+----+------------------+------+---------------------+
| id | name             | age  | created_at          |
+----+------------------+------+---------------------+
|  1 | Taro Yamada      | 30   | 2025-05-03 06:11:10 |
|  2 | Misaki Kawasaki  | 25   | 2025-05-03 06:16:15 |
|  3 | Hiroshi Uchiyama | 25   | 2025-05-03 06:17:09 |
|  4 | Ai Tada          | 35   | 2025-05-03 10:59:43 |
|  5 | Mitsuo Kino      | NULL | 2025-05-03 11:20:57 |
+----+------------------+------+---------------------+
5 rows in set (0.001 sec)
```


### 特定の列を取得する

#### `SELECT 列名1, 列名2 FROM テーブル名`

* **構文**
    * `SELECT 列名1, 列名2`:  取得したい列の名前をカンマ,で区切って指定します。
* **実行結果**
    * このクエリを実行すると、指定した テーブル名 から、列名1 と 列名2 のデータのみが抽出され、結果セットとして返されます。テーブル内の他の列のデータは表示されません。

##### 例：customersテーブルから name と age の列だけを取得

```sql
 -- SELECT文のサンプル
SELECT name , age FROM customers;
```
##### 出力結果
```
+------------------+------+
| name             | age  |
+------------------+------+
| Taro Yamada      | 30   |
| Misaki Kawasaki  | 25   |
| Hiroshi Uchiyama | 25   |
| Ai Tada          | 35   |
| Mitsuo Kino      | NULL |
+------------------+------+
5 rows in set (0.001 sec)
```
### 別名をつける

#### `SELECT 列名 AS 別の列名`

* **構文**
    * `AS 別の列名`: 元の列名に対して、結果セットで表示する際の新しい名前（エイリアス）を指定します。AS キーワードは省略可能な場合もありますが、明示的に記述する方が可読性が高まります。

* **実行結果**
    * このクエリを実行すると、指定した テーブル名 から 列名 のデータが抽出されますが、結果セットの列ヘッダーは 別の列名 として表示されます。元のテーブルの列名は変更されません。

##### 例：customersテーブル のid 列の行数を数え、その結果に numbers という別名を付ける

```sql
 -- SELECT文のサンプル
 SELECT count(id) AS numbers FROM customers;
```
##### 出力結果
```
+---------+
| numbers |
+---------+
|       5 |
+---------+
1 row in set (0.001 sec)
```

### 重複を排除する

#### `SELECT DISTINCT (列名)`

* **構文**
    * `SELECT DISTINCT (列名)`: DISTINCT キーワードは、続く列名の値が重複している行を一つにまとめ、一意な値だけを残します。括弧 () は省略可能な場合が多いですが、明示的に記述することもあります。

* **実行結果**
    * このクエリを実行すると、指定した テーブル名 の 列名 に存在する値の中で、重複している値は一つにまとめられ、一意な値のリストが結果セットとして返されます。

##### 例：customersテーブル のage 列に複数の同じ年齢の顧客がいる場合、一意な年齢だけを知りたい場合

```sql
 -- SELECT文のサンプル
select distinct(age) from customers;
```
##### 出力結果
```
+------+
| age  |
+------+
| 30   |
| 25   |
| 35   |
| NULL |
+------+
4 rows in set (0.002 sec)
```
## 条件を指定するwhere句



#### `SELECT 列名 FROM テーブル名 WHERE 検索`

* **構文**
    * `WHERE 検索`: データを抽出するための条件を指定します。この部分は、比較演算子、論理演算子、特殊なキーワードなどを組み合わせて記述します。

### 比較演算子

* `=` (等しい)
* `>` (より大きい)
* `<` (より小さい)
* `>=` (以上)
* `<=` (以下)
* `<>` または `!=` (等しくない)
##### 例：customersテーブルの age 列の値が 25 であるすべての列の行を抽出


```sql
 -- SELECT文のサンプル
  SELECT * FROM customers WHERE age = 25;
```
##### 出力結果
```
+----+------------------+------+---------------------+
| id | name             | age  | created_at          |
+----+------------------+------+---------------------+
|  2 | Misaki Kawasaki  | 25   | 2025-05-03 06:16:15 |
|  3 | Hiroshi Uchiyama | 25   | 2025-05-03 06:17:09 |
+----+------------------+------+---------------------+
2 rows in set (0.006 sec)
```

### 論理演算子

```SQL:論理演算子の記法
SELECT 列名
FROM テーブル名
WHERE 条件1 AND(OR,NOT) 条件2 AND(OR,NOT) ...;
```
#### AND：複数条件をすべて満たす行を取得

「条件1かつ条件2」の行を取得します

##### 例：customers テーブルから、age 列の値が 25 であり、かつ name 列の値が 'Hiroshi Uchiyama' である、すべての列の行を抽出

```sql
 -- SELECT文のサンプル
   SELECT * FROM customers WHERE age = 25 AND name = 'Hiroshi Uchiyama';
```
##### 出力結果
```
+----+------------------+------+---------------------+
| id | name             | age  | created_at          |
+----+------------------+------+---------------------+
|  3 | Hiroshi Uchiyama | 25   | 2025-05-03 06:17:09 |
+----+------------------+------+---------------------+
1 row in set (0.001 sec)
```

#### OR：いずれかの条件を満たす行を取得
「条件1または条件2」の行を取得します
##### 例：customers テーブルから、age 列の値が 30 であり、または name 列の値が 'Hiroshi Uchiyama' である、すべての列の行を抽出

```sql
 -- SELECT文のサンプル
   SELECT * FROM customers WHERE age = 30 OR name = 'Hiroshi Uchiyama';
```
##### 出力結果
```
+----+------------------+------+---------------------+
| id | name             | age  | created_at          |
+----+------------------+------+---------------------+
|  1 | Taro Yamada      | 30   | 2025-05-03 06:11:10 |
|  3 | Hiroshi Uchiyama | 25   | 2025-05-03 06:17:09 |
+----+------------------+------+---------------------+
2 rows in set (0.000 sec)
```

#### NOT：指定した条件を満たさない行を取得
「条件ではない」行を取得します

##### 例：customers テーブルから、age 列の値が 30 でない、または、name 列の値が 'Hiroshi Uchiyama' でない、すべての列の行を抽出

```sql
 -- SELECT文のサンプル
   SELECT * FROM customers WHERE NOT (age = 30 OR name = 'Hiroshi Uchiyama');
```
##### 出力結果
```
+----+-----------------+------+---------------------+
| id | name            | age  | created_at          |
+----+-----------------+------+---------------------+
|  2 | Misaki Kawasaki | 25   | 2025-05-03 06:16:15 |
|  4 | Ai Tada         | 35   | 2025-05-03 10:59:43 |
+----+-----------------+------+---------------------+
2 rows in set (0.001 sec)
```

### BETWEEN

指定した列の値が特定の範囲内にある行を抽出します

```SQL:BETWEENの記法
SELECT 列名
FROM テーブル名
WHERE 列名 BETWEEN 値1 AND 値2;
```
##### 例：customers テーブルから、age（年齢）という列の値が 25歳以上かつ30歳以下 である、すべての列の行を抽出

```sql
 -- SELECT文のサンプル
SELECT * FROM customers WHERE age BETWEEN 25 AND 30;
```
##### 出力結果
```
+----+------------------+------+---------------------+
| id | name             | age  | created_at          |
+----+------------------+------+---------------------+
|  1 | Taro Yamada      | 30   | 2025-05-03 06:11:10 |
|  2 | Misaki Kawasaki  | 25   | 2025-05-03 06:16:15 |
|  3 | Hiroshi Uchiyama | 25   | 2025-05-03 06:17:09 |
+----+------------------+------+---------------------+
3 rows in set (0.001 sec)
```

### IN / NOT IN

指定した列の値が複数の候補値のいずれかに一致するか（IN）、または一致しないか（NOT IN）

```SQL:IN, NOT INの記法
SELECT 列名
FROM テーブル名
WHERE 列名 IN(NOT IN) (値1, 値2, 値3, ...);
```
#### IN：複数の候補から一致する値を取得
「含む」行を取得します
##### 例：age 列の値が '25' または '30' のいずれかに一致するすべての列の行

```sql
 -- SELECT文のサンプル
SELECT * FROM customers WHERE age IN('25','30');
```
##### 出力結果
```
+----+------------------+------+---------------------+
| id | name             | age  | created_at          |
+----+------------------+------+---------------------+
|  1 | Taro Yamada      | 30   | 2025-05-03 06:11:10 |
|  2 | Misaki Kawasaki  | 25   | 2025-05-03 06:16:15 |
|  3 | Hiroshi Uchiyama | 25   | 2025-05-03 06:17:09 |
+----+------------------+------+---------------------+
3 rows in set (0.001 sec)
```

#### NOT IN：複数の候補から一致しない値を取得
「含まない」行を取得します
##### 例：customers テーブルから、age 列の値が '25' でも '30' でもないすべての列の行を抽出

```sql
 -- SELECT文のサンプル
SELECT * FROM customers WHERE age NOT IN('25','30');
```
##### 出力結果
```
+----+---------+------+---------------------+
| id | name    | age  | created_at          |
+----+---------+------+---------------------+
|  4 | Ai Tada | 35   | 2025-05-03 10:59:43 |
+----+---------+------+---------------------+
1 row in set (0.001 sec)
```
### IS NULL / IS NOT NULL
特定の列の値が NULL であるか、または NULL でないかを判定して行を抽出する

NULL は「値が存在しない」または「不明」であることを示す特別な値であり、0や空文字とは異なります。NULL との比較には専用の演算子を使う必要があります。

#### IS NULL：値が存在しない（NULL）の行を取得

列の値かNULLである行を取得
##### 例：customers テーブルから、age 列の値が NULL であるすべての列の行を抽出

```sql
 -- SELECT文のサンプル
SELECT * FROM customers WHERE age IS NULL;
```
##### 出力結果
```
+----+-------------+------+---------------------+
| id | name        | age  | created_at          |
+----+-------------+------+---------------------+
|  5 | Mitsuo Kino | NULL | 2025-05-03 11:20:57 |
+----+-------------+------+---------------------+
1 row in set (0.001 sec)
```
#### IS NOT NULL：値がNULLではない行を取得

列の値かNULLではない行を取得
##### 例：customers テーブルから、age 列の値が NULL ではないすべての列の行を抽出

```sql
 -- SELECT文のサンプル
SELECT * FROM customers WHERE age IS NOT NULL;
```
##### 出力結果
```
+----+------------------+------+---------------------+
| id | name             | age  | created_at          |
+----+------------------+------+---------------------+
|  1 | Taro Yamada      | 30   | 2025-05-03 06:11:10 |
|  2 | Misaki Kawasaki  | 25   | 2025-05-03 06:16:15 |
|  3 | Hiroshi Uchiyama | 25   | 2025-05-03 06:17:09 |
|  4 | Ai Tada          | 35   | 2025-05-03 10:59:43 |
+----+------------------+------+---------------------+
4 rows in set (0.001 sec)
```

### あいまい検索 (LIKE)
文字列のパターンマッチングを行うための演算子です。完全に一致する文字列だけでなく、特定の部分文字列を含む、あるいは特定のパターンに合致する文字列を持つ行を抽出する際に使用します。



```SQL:LIKE, NOT LIKEの記法
SELECT 列名
FROM テーブル名
WHERE 列名 LIKE(NOT LIKE) 'パターン';
```
#### LIKE：部分一致で文字列を検索

列の文字列の値が部分一致する行を取得する

`%` 0文字以上の任意の文字列
##### LIKE記法の例：
* `%Taro%`： 'Taro' で始まる任意の文字列
* `%yama%`： 任意の場所に 'yama' を含む文字列
* `%da` ：'da' で終わる任意の文字列
* `%` ：すべての文字列

##### 例：customers テーブルから、名前に 'uchi' を含む顧客を抽出する場合

```sql
 -- SELECT文のサンプル
SELECT * FROM customers WHERE name LIKE '%uchi%';
```
##### 出力結果
```
+----+------------------+------+---------------------+
| id | name             | age  | created_at          |
+----+------------------+------+---------------------+
|  3 | Hiroshi Uchiyama | 25   | 2025-05-03 06:17:09 |
+----+------------------+------+---------------------+
1 row in set (0.001 sec)
```

#### NOT LIKE：部分一致しない文字列を検索

列の文字列の値が部分一致しない行を取得する

##### 例：customers テーブルから、name 列の値に 'ma' という文字列を含まないすべての列の行を抽出

```sql
 -- SELECT文のサンプル
SELECT * FROM customers WHERE name NOT LIKE '%ma%';
```

##### 出力結果
```
+----+-----------------+------+---------------------+
| id | name            | age  | created_at          |
+----+-----------------+------+---------------------+
|  2 | Misaki Kawasaki | 25   | 2025-05-03 06:16:15 |
|  4 | Ai Tada         | 35   | 2025-05-03 10:59:43 |
|  5 | Mitsuo Kino     | NULL | 2025-05-03 11:20:57 |
+----+-----------------+------+---------------------+
3 rows in set (0.001 sec)
```

## 並び替える (ORDER BY句)

クエリの結果セットを指定した列の値に基づいて並び替える

ORDER BY 句は、WHERE 句の後に記述します

```SQL:ORDER BY 句の記法
SELECT *
FROM customers
WHERE 条件; -- (もし条件があれば)
ORDER BY 並び替える列名 [ASC|DESC];
-- ASC は昇順 (デフォルト)で DECS は降順
```

* **構文**
    * `ORDER BY 並び替える列名`: 並び替えの基準となる列の名前を指定します。
    * `[ASC|DESC]`: 並び替えの順序を指定します。

* **実行結果**
    * このクエリを実行すると、指定した テーブル名 の 列名 に存在する値の中で、重複している値は一つにまとめられ、一意な値のリストが結果セットとして返されます。


### 昇順

#### ASC（Ascending）
昇順に並び替えます（デフォルト）。小さい値から大きい値へ、AからZへ、古い日付から新しい日付へといった順序です。


##### 例：customers テーブルのageを昇順で並び替え

```sql
 -- SELECT文のサンプル
SELECT * 
FROM customers
ORDER BY age ASC;
```
##### 出力結果
```
+----+------------------+------+---------------------+
| id | name             | age  | created_at          |
+----+------------------+------+---------------------+
|  5 | Mitsuo Kino      | NULL | 2025-05-03 11:20:57 |
|  2 | Misaki Kawasaki  | 25   | 2025-05-03 06:16:15 |
|  3 | Hiroshi Uchiyama | 25   | 2025-05-03 06:17:09 |
|  1 | Taro Yamada      | 30   | 2025-05-03 06:11:10 |
|  4 | Ai Tada          | 35   | 2025-05-03 10:59:43 |
+----+------------------+------+---------------------+
5 rows in set (0.024 sec)
```

昇順がデフォルトなので下記のように ASC は省略可能です。

```sql
 -- SELECT文のサンプル
SELECT * 
FROM customers
ORDER BY age;
```

### 降順

#### DESC（Descending）
降順に並び替えます。大きい値から小さい値へ、ZからAへ、新しい日付から古い日付へといった順序です。
##### 例：customers テーブルのageを降順で並び替え
```sql
 -- SELECT文のサンプル
SELECT *
FROM customers
ORDER BY age DESC;
```
##### 出力結果
```
+----+------------------+------+---------------------+
| id | name             | age  | created_at          |
+----+------------------+------+---------------------+
|  4 | Ai Tada          | 35   | 2025-05-03 10:59:43 |
|  1 | Taro Yamada      | 30   | 2025-05-03 06:11:10 |
|  2 | Misaki Kawasaki  | 25   | 2025-05-03 06:16:15 |
|  3 | Hiroshi Uchiyama | 25   | 2025-05-03 06:17:09 |
|  5 | Mitsuo Kino      | NULL | 2025-05-03 11:20:57 |
+----+------------------+------+---------------------+
5 rows in set (0.003 sec)
```

特定の条件で絞り込んだ上で並び替えたい場合は、WHERE 句を先に記述します。

```sql
 -- SELECT文のサンプル
SELECT *
FROM customers
WHERE age >= 30
ORDER BY name DESC;
```

```
+----+-------------+------+---------------------+
| id | name        | age  | created_at          |
+----+-------------+------+---------------------+
|  1 | Taro Yamada | 30   | 2025-05-03 06:11:10 |
|  4 | Ai Tada     | 35   | 2025-05-03 10:59:43 |
+----+-------------+------+---------------------+
2 rows in set (0.005 sec)
```

複数条件で並び替える

```sql
 -- SELECT文のサンプル
SELECT *
FROM customers
ORDER BY age DESC, created_at DESC;
```

```
+----+------------------+------+---------------------+
| id | name             | age  | created_at          |
+----+------------------+------+---------------------+
|  4 | Ai Tada          | 35   | 2025-05-03 10:59:43 |
|  1 | Taro Yamada      | 30   | 2025-05-03 06:11:10 |
|  3 | Hiroshi Uchiyama | 25   | 2025-05-03 06:17:09 |
|  2 | Misaki Kawasaki  | 25   | 2025-05-03 06:16:15 |
|  5 | Mitsuo Kino      | NULL | 2025-05-03 11:20:57 |
+----+------------------+------+---------------------+
5 rows in set (0.004 sec)
```

## データ数を限定する (LIMIT句) 

```SQL:LIMIT 句の記法
SELECT 列名1, 列名2, ...
FROM テーブル名
LIMIT 件数;
```
例：テーブルの先頭から3件のレコードを取得したい場合
```sql
 -- SELECT文のサンプル
SELECT *
FROM customers
LIMIT 3;
```

##### 出力結果
```
+----+------------------+------+---------------------+
| id | name             | age  | created_at          |
+----+------------------+------+---------------------+
|  1 | Taro Yamada      | 30   | 2025-05-03 06:11:10 |
|  2 | Misaki Kawasaki  | 25   | 2025-05-03 06:16:15 |
|  3 | Hiroshi Uchiyama | 25   | 2025-05-03 06:17:09 |
+----+------------------+------+---------------------+
3 rows in set (0.002 sec)
```


## まとめ

本記事では、SQLの最も基本的な命令である `SELECT` 文について、以下の点を中心に解説しました。

- テーブルからの全件取得（`SELECT *`）
- 特定列の取得、別名の付与（`AS`）
- 条件付き取得（`WHERE`、`IN`、`BETWEEN` など）
- NULLの取り扱い

SELECT文は、データベースから必要な情報を効率的に取得するための強力なツールです。こういった基礎を身につけることで、より複雑なデータ操作や分析を行うための土台を築くことができると思います。

次回の記事では、リレーショナルデータベースの設計における重要な概念である「データベースの正規化」について解説する予定です。引き続き、独学での学習の成果を共有していきたいと思いますので、ご覧いただければと思います。