SQL 基礎の備忘録

#はじめに
SQLって意外とちゃんと習ったことが無いような気がして、現場では使っているけどちゃんと復習した際に、あ〜なるほど、そうですよね！ってなったことをメモします（タイトルにありますが、念のためもう一度。**基礎**です。）
* mysqlほぼ使ったことないですが一応mysqlを前提とします。

#Primary Keys
いやいやそんなこと忘れんな！って話ですがおさらい。

- 列に対してユニークな値を保持するためのKey
- `NULL`は保持できない

#SQLの書き方
- 大文字小文字の区別は無い
- **大抵は大文字で揃える**
- 空白と改行は無視される
- 文字列はシングルクオーテーション('')で囲む

#SQL Operator
- = (Equal)
- != (Not Equal)
- > (Greater than)
- < (Smaller than)
- >= (Greater than or Equal)
- <= (Smaller than or Equal)
- BETWEEN (Between the range)

#データ型
- INT
- FLOAT
- DOUBLE
- DATE *(YYYY-MM-DD)*
- DATETIME *(YYYY-MM-DD HH:MM:SS)*
- TIMESTAMP *(January 1, 2000)*
- TIME *(HH:MM:SS)*
- CHAR
- VARCHAR
- BLOB (Large Binary data such as an image)
- TEXT (Large text data)

#Basic Commands
###データベースの表示
```sql
SHOW DATABASES;
```
###テーブルの表示
```sql
SHOW TABLES;
```
###テーブルの情報表示
Field, Type, key, Default, Extraが表示される

```sql
SHOW COLUMNS FROM TABLE;
```
###レコードの選択
asterisk(*) の意味はALLとなる

```sql
SELECT * FROM TABLE;
```
###ユニークな値だけを取得
```sql
SELECT DISTINCT COLUMN_NAME FROM TABLE
```
###結果行数の指定
最初の例は10行だけ表示。
二番目の例は結果の3番目のポジションから10行だけを表示。
(mysqlは行数0から始まっているので行数が表示される場合+1になります）

```sql
SELECT COLUMN_NAME FROM TABLE LIMIT 10;
SELECT COLUMN_NAME FROM TABLE LIMIT 3, 10;
```
###レコードの並び替え
Defaultの並び順は`ASC`（昇順）です。降順にしたい場合は`DESC`をカラム名の後につけます。
`ORDER BY`に複数カラムを指定した場合は、最初のカラムにて並び順がまず適用されます。そのあと2番目以降のカラム順で並びます。

```sql
SELECT FROM COLUMN_NAME FROM TABLE ORDER BY COLUMN_NAME;
```

###取得する値の範囲指定
例では1~3の範囲でSELECT

```sql
SELECT * FROM TABLE 
WHERE ID BETWEEN 1 AND 3;
```

###WHERE句のオプション

- AND (指定した条件が全てTRUEの場合値が返る)
- OR　(指定した条件どれかがTRUEの場合値が返る)
- IN　(複数指定した条件が全てTRUEの場合値が返る)
- NOT （指定した条件がFALSEの場合値が返る）

`AND`と`OR`を併せた場合

```sql
SELECT * FROM TABLE
WHERE COLUMN = 'A'
AND (NO = 10 OR NO = 15);
```
`IN`の場合。
`IN`の前に`NOT`をつければ条件に満たさない結果が返ってきます。

```sql
SELECT * FROM TABLE 
WHERE COLUMN IN ('A', 'B', 'C');
```

###複数列の値を結合したい場合
`CONCAT`を使います。間に挟んだ値で結合できます。
例だと `,` で値が結合されます。

```sql
SELECT CONCAT(COLUMN_1, ', ' , COLUMN_2) FROM TABLE;
```

`AS`を使うことで結合した列の名前を指定できます。

```sql
SELECT CONCAT(COLUMN_1, ', ' , COLUMN_2) AS NEW_COLUMN FROM TABLE;
```
###列の値を計算して結果を出力
また、列名に `+`, `-`, `*`, `/` といった計算をさせることも可能で、この結果に対して`AS`を使うこともできます。

```sql
SELECT COLUMN_1, NO+10 AS NEW_NO FROM TABLE;
```

###結果を大/小文字にしたい時
`UPPER` / `LOWER` を使います。

```sql
SELECT UPPER(COLUMN) AS UPPER_COLUMN FROM TABLE;
```

###平均値や合算値を求める

```sql
SELECT AVG(COLUMN) FROM TABLE;
SELECT SUM(COLUMN) FROM TABLE;
SELECT MAX(COLUMN) FROM TABLE;
SELECT MIN(COLUMN) FROM TABLE;
```
###複数のSQLを一度にやっちゃいたい
Aの条件をして、次にBの条件をして、結果をだすという時に2つのSQLを書かずに1つのSQLで一気にやっちゃいたい時に。
`()`で囲むのが大切です。

```sql
SELECT NO, FROM TABLE 
WHERE NO > (SELECT AVG(NO) FROM TABLE) 
ORDER BY NO DESC;
```

###曖昧な検索がしたいとき
`LIKE`を使います。例だとAから始まる名前のレコードが結果として返ってきます。
ワイルドカードは`%`です。

```sql
SELECT NAME FROM TABLE WHERE NAME LIKE 'A%';
```

#Table Operation
##JOIN (結合）
JOINは複数のテーブルに同じ列名（もしくは同じ意味合いの値を持つ列）がある場合、
それらを軸として複数のテーブルから同時に値を取得する感じです。
二個目のSQLはテーブルに簡易的な名前をつけている例で、取得できる値はもちろん丁寧に書いた一つ目と変わりません。

```sql
SELECT TABLE_A.COLUMN_1, TABLE_B.COLUMN_2 FROM TABLE_A, TABLE_B WHERE TABLE_A.NO = TABLE_B.NO;

SELECT A.COLUMN_1, B.COKUMN_2 FROM TABLE_A AS A, TABLE_B AS B WHERE A.NO = B.NO;
```

さて恒例の、JOINのタイプについてです。
##INNER JOIN
INNER JOINに関しては上記のただの`JOIN`に対して変わりはありません。（`INNER JOIN`、`ON`と明示的に書く必要はあります）
複数テーブルから、マッチした値を取得します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484310/aab4900e-cd0a-14ff-93ed-ed5c29695d45.png)

```sql
SELECT NO FROM TABLE_1 INNER JOIN TABLE_2 ON TABLE_1.NO = TABLE_2.NO;
```
##LEFT JOIN
複数テーブル間でマッチした値と、左側のテーブルの検索条件にマッチした値を返します
`OUTER`に関してはoptionalです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484310/e681f853-6695-d8ef-992f-d764f9063966.png)

```sql
SELECT COLUMN_A, COLUMN_B FROM TABLE_1 LEFT (OUTER) JOIN TABLE_2 ON TABLE_1.NO = TABLE_2.NO;
```

##RIGHT JOIN
複数テーブル間でマッチした値と、右側のテーブルの検索条件にマッチした値を返します
`OUTER`に関してはoptionalです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484310/c7517a1a-086b-ac30-68e8-cf95f5699ebe.png)

```sql
SELECT COLUMN_A, COLUMN_B FROM TABLE_1 RIGHT (OUTER) JOIN TABLE_2 ON TABLE_1.NO = TABLE_2.NO;
```

##UNION
複数テーブルを結合し、重複データを削除した値が返ってきます。しかし行うには下記条件があります。
- 結合する列は同じデータ型であること。
- 結合する列は同じ並びで指定すること。
もし列が片方のテーブルで足りない場合は、`NULL`を指定することで実行できます。

```sql
SELECT COLUMN_1, COLUMN_2 FROM TABLE_A UNION SELECT COLUMN_1, COLUMN_2 FROM TABLE_B;

SELECT COLUMN_1, COLUMN_2 FROM TABLE_A UNION SELECT COLUMN_1, NULL FROM TABLE_B;
```

##UNION ALL
`UNION ALL`は重複した値を削除しない。そのため**`UNION`より実行速度が早い。**

##INSERT
INSERTはたまに構文忘れる。

```sql
INSERT INTO TABLE VALUES (VALUE_1, VALUE_2, VALUE_3);

INSERT INTO TABLE (COLUMN_1, COLUMN_2, COLUMN_3) VALUES (VALUE_1, VALUE_2, VALUE_3);
```
##UPDATE
一度`WHERE`句をつけ忘れてしまい、全てのテーブルデータをUPDATEしてしまったことがありました泣
何があっても`WHERE`をつけましょう！！

```sql
UPDATE TABLE SET COLUMN_1 = VALUE_1, COLUMN_2 = VALUE_2 WHERE condition;
```

##DELETE

```sql
DELETE FROM TABLE WHERE NO = 1;
```

##CREATE TABLE
カラム名、データ型と指定します。
カラムに下記オプションを持たせることができます。データ型宣言の後に指定します。

- NOT NULL
- UNIQUE
- PRIMARY KEY (これだけ最下部に指定する)
- CHECK
- DEFAULT
- AUTO_INCREMENT (値がインサートされるたびに自動でインクリメント)

```sql
CREATE TABLE TABLE_1
(
   COLUMN_1 int,
   COLUMN_2 varchar(100), 
   COLUMN_3 varchar(100),
   COLUMN_4 varchar(100),
   PRIMARY KEY(COLUMN_1)
); 
```

##ALTER TABLE
`ADD`はカラムの追加（DEFAULT値はNULLになる）
`DROP`はカラムの削除

```sql
ALTER TABLE TABLE ADD COLUMN_5 DATE;
ALTER TABLE TABLE DROP COLUMN_5 DATE;
ALTER TABLE TABLE CHANGE COLUMN_5 COLUMN_6 TIMESTAMP;
RENAME TABLE COLUMN_6 TO COLUMN_7
```

##CREATE VIEW

```sql
CREATE VIEW TMP AS SELECT COLUMN_1, COLUMN_2 FROM TABLE;
SELECT * FROM TMP;

REPLACE VIEW TMP AS SELECT COLUMN_1, COLUMN_2 FROM TABLE;
DROP VIEW TMP;
```