SQLコマンド一覧

# SQLの実行順序
SQLのコマンドはそこまで多くありません。これらを覚えるよりも、それらをどのように使うかを考えていくことの方が大切のように思います。

コマンドを確認する前に、個人的にSQLを触っていて、実行する順番が大切だと感じたので、まずは順番を載せておきます。

思った通りの結果にならないなと思ったら、実行の順番を確認してみてください。
あとは実行する前にどんなテーブルになるかイメージするとより早く理解できると思います！

| 1 | 2 |
|:-:|:-:|
|テーブルの指定|FROM   |
|結合|ON/JOIN   |
|検索|WHERE   |
|グループ化|GROUP BY   |
|関数|COUNT/SUM/AVG/MIN/MAX|
|HAVING|HAVING|
|検索|SELECT/DISTINCT|
|順序|ORDER BY|
|LIMIT|LIMIT|

# SQLコマンド一覧
## FROM 
これはどのテーブルからデータを取得するか決定します。
```
FROM publish
```
テーブル名の後に任意のエイリアスを作ることもできます。
```
FROM publish pub
```

## SELECT
SELECTはさまざまな書き方ができます。
これはどのカラムを取得したいか決定します。

| コマンド| 説明 |
|:-:|:-:|
|SELECT *   |全てのカラムを取得  |
|SELECT price   |priceカラムを取得   |
|SELECT price AS "価格"   |priceカラムを取得する。ただし、名前は価格とする。   |
|SELECT price, name   |priceとnameカラムを取得する。|
|SELECT DISTINCT name   |nameカラムを重複なしで取得する。|
|SELECT price * 1.10 AS tax |priceカラムに1.10を掛けた値を取得する。ただし名前はtaxとする。|
|SELECT count(*)   |カラム数をカウントする。|
|SELECT SUM/AVG(price) |priceカラムの合計や平均を取得する。|
|SELECT MIN/MAX(price)   |priceカラムの最小値や最大値を取得する。|

:::note 
*の場合はnullを含むが、nameなどにした場合はnullはカウントされない。
:::

## WHERE
WHEREは条件に合ったレコードを取得します。
色々な検索の仕方がありますが、代表的なのは以下のような書き方です。
| コマンド | 説明 |
|:-:|:-:|
|WHERE price = 1000  |priceが1000のデータを取得する。|
|WHERE name LIKE %太郎%  |nameが〜太郎〜に一致するデータを取得する。|
|WHERE NOT price >= 1000  |priceが1000以上でないデータを取得する。|
|WHERE price IS NULL   |priceがnullのデータを取得する。|
|WHERE price IS NOT NULL|priceがnullでないデータを取得する。|
|WHERE price = 1000 AND name = "太郎"   |priceが1000かつnameが太郎のデータを取得する。   |
|WHERE price = 1000 OR name = "太郎"   |priceが1000またはnameが太郎のデータを取得する。  |

## GROUP BY
カラム名を指定して、同じ項目がある場合はそれを１つのまとまりとします。

例えば、以下の場合は、購入日ごとにグループ化され、それぞれのグループの価格と購入日をpurchasesテーブルから取得します。
```
SELECT count(price), purchased_at
FROM purchases
GROUP BY purchased_at
```
GROUP BYを用いる場合、SELECTで使えるのは、GROUP BYに指定しているカラム名と、集計関数のみです。


GROUP BYは複数のカラム名を適用させることができ、その場合は、以下のようにカラム名同士をコンマ(,)で繋げます。
```
SELECT sum(price), purchased_at, character_name
FROM purchases
GROUP BY purchased_at, character_name;
```

GROUP BYはWHEREとも併用することができ、その場合はWHEREの後に書きます。


こちらはwhereで検索した場合です。
```
SELECT sum(price), name, purchased_at
FROM purchases
WHERE name = "太郎";
```
| sum(price)  | name |  purchased_at |
|:-:|:-:|:-:|
| 12000  |太郎 |2017-07-01   |

そして、そのwhereで取得したところから、購入日でグループ化しています。
```
SELECT sum(price), name, purchased_at
FROM purchases
WHERE name = "太郎"
GROUP BY purchased_at;
```
| sum(price)  | name |  purchased_at |
|:-:|:-:|:-:|
| 120  |太郎  |2019-07-01   |
| 1200  |太郎  |2019-07-02   |
| 3000  |太郎  |2019-07-03   |
| 2200  |太郎  |2019-07-04   |
| 1200  |太郎  |2019-07-05   |
| 省略 |

## ORDER BY
GROUP BYと見た目は似ていますが、ORDER BYは順番を並べ替えます。
書き方は以下の通りです。
```
* 降順の場合
ORDER BY TABLENAME DESC
* 昇順の場合
ORDER BY TABLENAME DESC
```


## LIMIT
これは検索した後に、"LIMIT 件数"のように、取得したいレコードの件数を決定します。
```
SELECT count(price), purchased_at
FROM purchases
LIMIT 5;
```

## HAVING
GROUP BYでグループ化したデータを更に絞り込みたい場合には、HAVINGを用います。
「GROUP BY カラム名 HAVING 条件」のようにすることで、条件を満たすグループを取得することができます。
whereに似ていますが、whereはgroup_byの前、havingは後に実行されます。

# サブクエリ
SQLでは、クエリの中に他のクエリを入れることができます。この他のクエリをサブクエリと言います。2つ以上のクエリを1つにまとめることができるので、より複雑なデータを取得する際に使われます。

```
SELECT name
FROM players
WHERE goals > (
  SELECT goals
  FROM players
  WHERE name = "太郎"
);
```
```
SELECT *
FROM countries
WHERE rank < (
  SELECT rank
  FROM countries
  WHERE name = "日本"
);
```

```
SELECT name,goals
FROM players
WHERE goals > (
SELECT avg(goals)
FROM players
);
```

* 7000円以下で「パーカー」より利益が高い商品を取得
```
SELECT name, price - cost
FROM items
WHERE price <= 7000
AND price - cost > (
SELECT price - cost
FROM items
WHERE name = "パーカー"
);
```


## AS

ASを使って、取得したカラム名を"身長180cm以上の選手"とする。
```
SELECT name AS "身長180cm以上の選手"
FROM players
```

# テーブルの関連づけ
```
SELECT *
FROM テーブルA
JOIN テーブルB
--結合条件を追加してください
ON テーブルA.カラム名（外部キー） = テーブルB.カラム名（主キー）
```
```
SELECT *
FROM players
JOIN countries
ON players.country_id = countries.id;
```

## 複数テーブルでのカラムの指定
複数のテーブルに同じカラム名が存在するときは、「テーブル名.カラム名」で指定しなければなりません。例えば、図のようにnameカラムが複数のテーブルにあるときは、「それぞれのテーブル名.name」で指定します。

:::note 
外部キーがNULLのレコードは、実行結果に表示されません。
:::

## LEFT JOIN
LEFT JOINを使うことで、FROMで指定したテーブルのレコードを全て取得します。外部キーがNULLのレコードもNULLのまま実行結果に表示されます。


## 3つのテーブル結合
JOINは1つのクエリで、複数回使用できます。JOINを複数回使用しても、FROMは1度だけ書けば大丈夫です。
```
SELECT *
FROM players
JOIN countries
ON players.country_id = countries.id
LEFT JOIN teams
ON players.previous_team_id = teams.id;
```