SQL備忘録

# 初めに
最近、DjangoのORMが発行しているqueryを見る機会がありました。
しかし、僕自身SQLについて勉強をあまりしたことがなかったので、ORMが発行するqueryを見てもチンプンカンプンでした。
そこで、SQLの勉強がしたくなったので勉強し始めました（完全に趣味）

僕のSQL備忘録として、記事に残したいと思います

# SQL
データベース(RDBMS)を操作するための言語。

大きく分けて３種類の言語から構成されている

- データ定義言語(Data Definition Language)
    - DDLと略される
    - RDBMSで扱うオブジェクト(テーブルやインデックスなど)の構造や、オブジェクト同士の関係を定義する構文  
    - `CREATE`, `JOIN`, `DROP`, `ALTER`, `TRUNCATE`などが存在

- データ操作言語(Data Manipulation Language)
    - DMLと略される
    - データベースを操作するための構文
    - データ取得、追加、更新、削除などの操作ができる
    - SQL関数と呼ばれる関数を使用できる
    - `SELECT`, `INSERT`, `DELETE`, `UPDATE`などが存在
- データ制御言語(Data Control Language)
    - DCLと略される
    - データへのアクセスを制御する構文
    - トランザクションやシステムの管理、アクセス権を制御する
    - `GRANT`, `REVOKE`, `BEGIN`, `COMMIT`, `ROLLBACK`などが存在

## 基本
`SELECT`: カラムを指定し、データを取得  
`FROM`: テーブルを指定

```SQL
SELECT 
    id,
    name
FROM
    users;
```
アスタリスクですべてのカラムを選択できる

```SQL
-- すべてのカラムを取得
SELECT
    *
FROM
    users;
```

`WHERE`: 条件を追加できる。`=` は完全一致

```SQL
-- usersテーブルのnameがAliceであるデータを取得
SELECT
    *
FROM
    users
WHERE
    name = "Alice";
```

`LIKE`: 指定したカラムが○○を含むようなレコードを取得。WHERE句で使用。 対象のカラムに対して文字列検索   
ワイルドカード: どんな文字列にも一致することを指す記号  

比較文字列に使用可能なワイルドカード  
`%`: 0文字以上の任意の文字列  
`_`: １文字の任意の文字列  

部分一致

```SQL
-- purchasesテーブルのnameカラムについて、"アメ"を含むデータ全て取得
SELECT
    *
FROM
    purchases 
WHERE
    name LIKE "%アメ%";
```

前方一致

```SQL 
-- purchasesテーブルのnameカラムについて、"アメ"から始まる含むデータ全て取得
-- アメ、アメ玉など
SELECT
    *
FROM
    purchases
WHERE
    name LIKE "アメ%";
```

後方一致

```SQL 
-- purchasesテーブルのnameカラムについて、"アメ"で終わるデータ全て取得
-- アメ、みかんアメ、ラムネアメなど
SELECT
   *
FROM
    purchases
WHERE
    name LIKE "％アメ";
```

`NOT`: 否定を意味する

```SQL
-- purchasesテーブルのpriceカラムの値が1000以下のものを取得
SELECT
    *
FROM
    purchases
WHERE
    NOT price > 1000;
```

```SQL 
-- purchasesテーブルのnameカラムについて、"アメ"を含まないデータ全て取得
SELECT
    *
FROM
    purchases
WHERE
    name NOT LIKE "％アメ％";
```

NULLデータ取得

```SQL
SELECT
    *
FROM
    purchases
WHERE
    price IS NULL;
```
NULLではないデータ取得

```SQL
SELECT
    *
FROM
    purchases
WHERE
    price IS NOT NULL;
```

NULLを扱う時は `=` ではダメ

```SQL
-- これはダメ
SELECT
    *
FROM
    purchases
WHERE
    price = NULL;
```

`ORDER BY`: 並び替え  
ASC(昇順)、DESC(降順)   
WHERE条件の後ろに記述。
WHERE条件を指定しない場合はFROM句の後にORDER BY句を記述

```SQL
-- purchasesテーブルのpriceカラムを降順にし、データを取得
SELECT
    *
FROM
    purchases
ORDER BY
    price DESC;
```

`LIMIT`: 最大何件取得するか指定。クエリの末尾に記述し、取得するデータ数を制限

```SQL
-- purchasesテーブルから最大５件のデータを取得
SELECT
    *
FROM
    purchases
LIMIT
    5;
```

## 集合関数
集合関数: 引数に指定したカラムの値を集計し結果を返す。  
WHERE条件が指定されている場合は、抽出されたレコードを対象に集計した結果を返す。

`SUM`: 引数の総和を求める。NULLの場合は集計対象外  
`MAX`: 引数の最大値を求める。  
`MIN`: 引数の最小値を求める。  
`AVG`: 引数の平均値を求める。NULLの場合は集計対象外  
`COUNT`: 引数の値の総数を求める。NULLの場合は集計対象外

```SQL
-- employeeテーブルから、salary(給料)の総和、最大値、最小値、平均値、総数を求める
SELECT
    SUM(salary),
    MAX(salary),
    MIN(salary),
    AVG(salary),
    COUNT(salary)
FROM
    employee;
```

## ちょい発展
`BETWEEN`: カラムの値の上限値と下限値を指定。下限値以上、上限値以下の場合、真を返す。WHERE句で使用。

```SQL
-- employeeテーブルから、salary(給料)が1000以上, 2000以下の従業員のnameとsalaryデータを取得
SELECT
    name,
    salary
FROM
    employee
WHERE
    salary
BETWEEN
    1000 AND 2000;
```

比較演算子を用いると以下のように書き換え可能

```SQL
SELECT
    name, 
    salary
FROM
    employee
WHERE
    1000 <= salary
AND salary <= 2000;
```

否定のときは、BETWEEN演算子の前にNOTを記述

```SQL
-- employeeテーブルからsalary(給料)が1000未満か、2000より多い従業員のEname, salaryデータを取得
SELECT
    name,
    salary
FROM
    employee
WHERE
    salary
NOT BETWEEN
    1000 AND 2000;
```

`GROUP BY`: 指定したカラムごとにグループ化し、集計関数の計算結果を取得できる。  
SELECT文に指定できるカラムは、GROUP BYで指定したカラムと、集計関数。

>WHERE条件を記述可能。
まず、WHERE条件よりレコードが抽出される。
その後GROUP BY で指定したカラムごとにグループ化され、集計関数で計算結果が求められる。

```SQL
-- employeeテーブルからdepartment(部署番号)毎に、departmentとsalaryの平均を取得
SELECT
    department,
    AVG(salary)
FROM
    employee
GROUP BY
    department;
```

# 参考サイト
http://sql.main.jp/

# さいごに
SQLについてまだまだ勉強中ですので、こちらの記事は随時更新していきたいと思います