応用情報技術者試験 SQLの一歩進んだ学習

本稿は、応用情報技術者試験のデータベース分野に不可欠であるSQL知識を、具体的なテーブル操作を通じて理解を深めるものです。

基本情報技術者試験で出題されるSQLが大まかにわかる方向けです。

今回の内容は以下の動画でも解説しています。

<iframe width="560" height="315" src="https://www.youtube.com/embed/l0gNcUV1Z7A?si=2PLNKTZUG9jdKM2R" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

:::note warn
独自の解釈により、不適切な表現がある可能性があります。不適切な表現があった場合、その都度修正していきます。
:::

# SQL SELECT文における句の実行順序

SQLクエリの句の論理的な実行順序は以下のとおりです。

## 論理的な実行順序（概要）
| 順 | SQL句    | 説明                                       |
|------|---------|----------------|
| 1   | FROM句      | テーブルを指定します。                                                    |
| 2   | JOIN句      | 複数テーブルの結合方法を指定します。                                                     |
| 3   | WHERE句     | 行の抽出条件を指定します。                                                          |
| 4   | GROUP BY句  | 行をグループ化します。                                                              |
| 5   | HAVING句    | グループ毎の集計結果に基づいて、さらにデータを絞り込む条件を指定します。                |
| 6   | SELECT句    | 出力する列を指定します。                                                            |
| 7   | ORDER BY句　　  | 結果セットをソートします。     |



---

# 結合 (JOIN) について

結合 (JOIN) は、複数のテーブルから関連するデータを組み合わせて取得するための機能です。
結合の種類を理解することで、目的に応じたデータ抽出が可能になります。


# クロス結合 
## (FROM テーブルA CROSS JOIN テーブルB;)

*   テーブルAとテーブルBの**すべての行**を組み合わせる
*   結合条件は**不要**

※下記、CROSS JOINの結果の表にある foreign_key_b カラムの値について、先頭の2桁は誤記です。申し訳ございません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618291/a9a98505-4653-4eec-9211-6cd52f01a050.png)


---

# 内部結合 
## (FROM テーブルA INNER JOIN テーブルB ON 結合条件;)

*   テーブルAとテーブルBで**結合キーが一致する行のみ**を結合
*   一致しない行は**除外**される
*   両方のテーブルにデータが存在する行のみ取得したい場合に利用

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618291/c239c9da-6eeb-488a-9e73-8a39f1e06f1f.png)


---

# 左外部結合 
## (FROM テーブルA LEFT OUTER JOIN テーブルB ON 結合条件;)

*   テーブルA (左側) の**すべての行**を残す
*   テーブルB (右側) で結合キーが一致する行を結合
*   テーブルBに一致する行がない場合、テーブルB側のカラムは**NULL**になる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618291/61c14bb3-e1d0-423c-b111-21e659b4fc2b.png)


---

# 右外部結合 
## (FROM テーブルA RIGHT OUTER JOIN テーブルB ON 結合条件;)

*   テーブルB (右側) の**すべての行**を残す
*   テーブルA (左側) で結合キーが一致する行を結合
*   テーブルAに一致する行がない場合、テーブルA側のカラムは**NULL**になる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618291/1fe482af-a58e-4e65-a35e-c7d6a2f8c001.png)




---
## サブクエリと相関副問い合わせ

* **サブクエリ**: SQLクエリ内に入れ子になったクエリ
* **相関副問い合わせ**:
    * サブクエリが**外側のクエリ（主クエリ）の各行に依存**して実行
    * 主クエリの行ごとにサブクエリが**繰り返し評価**される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618291/ad9dcca3-afab-4a76-ae37-8fec66869681.png)


---
## 相関副問い合わせの動きと結果

```sql
SELECT *
FROM XMemberT A
WHERE A.Value1>= (
    SELECT AVG(B.Value1)
    FROM XRelationT B
    WHERE B.MemberID = A.MemberID -- 相関部分！
);
```

1. **主クエリ (`XMemberT A`) が1行ずつ処理**
2. **各行 (`A`) に対して、サブクエリが実行**:
   - `WHERE B.MemberID = A.MemberID` によって、`A` の `MemberID` と同じ `MemberID` を持つ `XRelationT (B)` のレコードのみを処理
   -  それらのレコードの `Value1` の平均 (`AVG(B.Value1)`) を計算
3. **主クエリの `WHERE A.Value1 >= (サブクエリ)` で比較**:






---
# GROUP BY
SQLでデータ集計処理を行うことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618291/fbdfe24a-ba9b-4a69-a721-bb3f90fa6672.png)


---
# GROUP BY

* **GROUP BY句**: 指定したカラムでデータをグループ化
* **集計関数**: グループごとに合計、平均などを計算 (`SUM`, `AVG`, `COUNT` など)
* **HAVING句**: 集計後のグループに対して条件を指定し絞り込み
* **SELECT句**: 最終的な出力カラムを指定 (集計関数も含む)


---
# SQLの例
```sql
SELECT
    カテゴリ,
    SUM(値1),
    AVG(値2)
FROM
    テーブル
GROUP BY
    カテゴリ
HAVING
    AVG(値2) > 100;
```



---

# 標準SQLにおけるセミコロン (;) の意味

## SQL文の区切り記号

* セミコロン (`;`) は、標準SQLにおいて**文の区切り**を表します。
* 複数のSQL文を記述する場合、それぞれの文を `;` で区切ることで、**独立したSQL文として認識**されます。

```sql
SELECT * FROM table1;
SELECT * FROM table2;
```

---

## セミコロンの役割

* **文の区切り:**  SQL文の終端を明確にし、複数の文を区別します。
* **可読性の向上:**  コードを読みやすく整理し、文の区切りを視覚的に認識しやすくします。
* **スクリプト実行:**  SQLスクリプト (複数のSQL文をまとめたファイル) を実行する際に、文の区切りを正しく認識させるために必要です。