たまにSQL文を書く時に、いつも調べちゃうことメモ

私は普段の業務ではフレームワークやO/Rマッパーライブラリを用いてRDBを操作する記述を書くことが多いので、SQL文自体を書くことが少ないエンジニアです。
ただ、たまにデータの分析や他のシステムへデータを連携させるために、直接SQL文を書いてデータを引っ張ってくる業務が発生します。
そのような中で、なんか毎回調べ直してるなってことを、自分用にメモしておこうと思い、記事を作成しました。

# シングルクォート(')、ダブルクォート(")、バッククォート(`)の違い
SQLはISOで国際標準化した規格なのですが、ベンダーごとに対応状況に差があり、また、独自の拡張や変更があるため混乱しやすいです。特に掲題の部分は、文字列扱いだっけ？識別子(テーブル名、カラム名)だっけ？がごちゃつきがちです。

- MySQL, Google BigQueryの場合

| 記号 | 扱い | 
|:-----------|------------:|
| シングルクォート(') | 文字列 |
| ダブルクォート(") | 文字列 |
| バッククォート(`) | 識別子(テーブル名、カラム名) |

[語彙の構造と構文](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical?hl=ja)

- PostgreSQLの場合

| 記号 | 扱い | 
|:-----------|------------:|
| シングルクォート(') | 文字列 |
| ダブルクォート(") | 識別子(テーブル名、カラム名) |
| バッククォート(`) | 使えない |

[語彙の構成](https://www.postgresql.jp/document/9.1/html/sql-syntax-lexical.html)

# (INNER) JOIN, LEFT (OUTER) JOIN, RIGHT (OUTER) JOINの結果の差
これは、見直すと、なぜ忘れるのか分からないけど、忘れるやつ。

サンプルテーブル

- foods

| name | category_id | 
|:-----------|------------:|
| じゃがいも | 1 |
| たまねぎ | 1 |
| にんじん | 1 |
| 鶏肉 | 3 |
| りんご | 2 |
| はちみつ | NULL |

- categories

| id | name | 
|:-----------|------------:|
| 1 | 野菜 |
| 2 | 果物 |
| 3 | 肉・魚 |
| 4 | 海藻類 |

## (INNER) JOIN
連結したときに、両方のテーブルで連結できたものだけが出力される
```
SELECT foods.name, categories.name FROM foods JOIN categories ON foods.category_id = categories.id;
```
| name | name | 
|:-----------|------------:|
| じゃがいも | 野菜 |
| たまねぎ | 野菜 |
| にんじん | 野菜 |
| 鶏肉 | 肉・魚 |
| りんご | 果物 |

## LEFT (OUTER) JOIN 
連結したときに、JOIN句の左に指定されたテーブルにあるものが出力される
```
SELECT foods.name, categories.name FROM foods LEFT JOIN categories ON foods.category_id = categories.id;
```
| name | name | 
|:-----------|------------:|
| じゃがいも | 野菜 |
| たまねぎ | 野菜 |
| にんじん | 野菜 |
| 鶏肉 | 肉・魚 |
| りんご | 果物 |
| はちみつ | NULL |

## RIGHT (OUTER) JOIN 
連結したときに、JOIN句の右に指定されたテーブルにあるものが出力される
```
SELECT foods.name, categories.name FROM foods RIGHT JOIN categories ON foods.category_id = categories.id;
```
| name | name | 
|:-----------|------------:|
| じゃがいも | 野菜 |
| たまねぎ | 野菜 |
| にんじん | 野菜 |
| 鶏肉 | 肉・魚 |
| りんご | 果物 |
| NULL | 海藻類 |

## FULL (OUTER) JOIN 
連結したときに、両方のテーブルの全てのレコードが出力される。
```
SELECT foods.name, categories.name FROM foods FULL JOIN categories ON foods.category_id = categories.id;
```
| name | name | 
|:-----------|------------:|
| じゃがいも | 野菜 |
| たまねぎ | 野菜 |
| にんじん | 野菜 |
| 鶏肉 | 肉・魚 |
| りんご | 果物 |
| はちみつ | NULL |
| NULL | 海藻類 |

# 複数のORDER BYの指定
カンマ(,)で並べていけば、書いた順で並び替えがされる。

サンプルテーブル
- users

| id | name | birthday | class | 
|:-----------|------------:|------------:|------------:|
| 1 | Momotaro | 2010-01-01 | 4 |
| 2 | Kintaro | 2012-08-07 | 2 |
| 3 | Urashimataro | 2010-04-05 | 4 |

classを昇順で並び替える。
```
SELECT * FROM users ORDER BY class ASC;
```
| id | name | birthday | class | 
|:-----------|------------:|------------:|------------:|
| 2 | Kintaro | 2012-08-07 | 2 |
| 1 | Momotaro | 2010-01-01 | 4 |
| 3 | Urashimataro | 2010-04-05 | 4 |

classを昇順で並び替えて、birthdayを降順で並び替える。
```
SELECT * FROM users ORDER BY class ASC, birthday DESC;
```
| id | name | birthday | class | 
|:-----------|------------:|------------:|------------:|
| 2 | Kintaro | 2012-08-07 | 2 |
| 3 | Urashimataro | 2010-04-05 | 4 |
| 1 | Momotaro | 2010-01-01 | 4 |

# ASC(昇順)とDESC(降順)どっちだっけ
昇順は小さいものから大きいものへ、降順は大きいものから小さいもの順

### 数値
ASC: 1,2,30,31...
DESC: 31,30,2,1...

### 文字列
文字コード順(一文字目が同じなら二文字というように評価していく)
ASC: aa,ab,bb,...
DESC: bb,ab,aa...

### 日付
ASC: 2000-01-01,2000-01-02,2001-01-01...
DESC: 2001-01-01,2000-01-02,2000-01-01...

# 行と列どっちだっけ
SQLとは関係ないけど、CSVとかにエクスポートした時、説明する時迷う。
よく、文字に注目して覚えればすぐわかるって言われるけど、不安になるのではっきり書いておく。

横が行、縦が列。レコード一件が行、カラムが列！