SQLコマンドまとめ

スッキリわかるSQL入門　第2版を読みながら、主に自分用の備忘録として残します。
dokoQLというサイトを使うと実際にSQL文を実行できます。
https://dokoql.com/d/Dokoqlv/index.html

実際のSQLでは--でコメントアウトですが、著者は//のコメントアウトが慣れているので、そのように記載します。
また、サンプルコードに関しては動作確認していないので、もしコードにバグや間違い等ありましたらご指摘頂けると幸いです。

#超基本
##データの検索：SELECT

```
SELECT 列名
FROM テーブル名

//ex：Expensesテーブルのすべての列を表示
SELECT *
FROM Expenses
```

##条件：WHERE

```
//WHEREで条件を加える
SELECT *
FROM Expenses
WHERE expenditure > 3000
```

##データの追加：INSERT INTO, VALUES

```
INSERT INTO テーブル名　（オプション：カンマ区切りで列名の指定）
VALUES (各列カンマ区切りで内容を入力)

//ex1：列名の指定なしで、すべての列にデータを追加（SELECT *と同じ順序で記載）
INSERT INTO Expenses
VALUES ('2018-02-25', 'housing', 'March rent', 0, 85000)

//ex2：列名を指定して、その列のみデータを追加（順序自由）
INSERT INTO Expenses (entry, date, expenditure)
VALUES ( 'housing', '2018-02-25', 85000)

//ex3：VALUESを使わず、副問い合わせによってデータを追加
INSERT INTO ExpenseArchives
SELECT * FROM Expenses
WHERE date < '2021-01-01';

```

##データの更新：UPDATE, SET

```
UPDATE テーブル名
SET 列 = 値
（必要に応じてWHEREで条件）

//ex
UPDATE Expenses
SET expenditure = 90000
WHERE date = '2018-02-25'
```

##データの削除：DELETE

```
DELETE FROM テーブル名
（必要に応じてWHEREで条件）

//ex
DELETE FROM Expenses
WHERE date = '2018-02-25'
```

#基本
##比較演算子
NULLの判定はこの比較演算子ではできないので、この下のNULLの判定を使ってください

```
=：等しい
<>：等しくない
<：左辺が小さい
>：左辺が大きい
<=：左辺が右辺以下
>=：左辺が右辺以上
```

## NULLの判定

```
//NULLである
式 IS NULL
//NULLでない
式 IS NOT NULL

//ex
SELECT *
FROM Expenses
WHERE expenditure IS NULL
```

##比較（一致）：IN, NOT IN
比較演算子だと1つしか比較できませんが、このINなどを使えば複数の比較ができます
INでは含むもの、NOT IN では全て含まないものが抽出対象になります

```
式　IN/NOT IN　(値1, 値2, ...)

//ex
//entryにfoodかsocializingが含まれているレコードを表示
SELECT *
FROM Expenses
WHERE entry NOT IN ('food', 'socializing')

//ex2
//entryにfoodとsocializingが含まれていないレコードを表示
SELECT *
FROM Expenses
WHERE entry NOT IN ('food', 'socializing')
```

## 複数の条件の組み合わせ：AND, OR

```
条件式1 AND/OR 条件式2

//ex
SELECT *
FROM Expenses
//expenditureが3000以上または、1000以下のデータを抽出
WHERE expenditure => 3000 OR expenditure　=< 1000
```

##真偽値の逆転：NOT
論理演算子の実行順序はNOT>AND>ORの順番で処理されるので、その点注意して下さい

```
NOT 条件式

//ex
SELECT *
FROM Expenses
//storeがB以外の時
WHERE NOT store = 'B'
```

##パターンマッチング：LIKE, ESCAPE
パターン文字列を使うことでパターンにマッチした文字列を表現できる
文字列として%や_を使いたい場合はESCAPEが必要になる

```
式　LIKE パターン文字列（下記参照）
%：任意の0文字以上の文字列
_：任意の1文字

//ex1
//例えば以下のパターンマッチではExpensesのmemo列で「january 3rd」や「2021 january rent」などと表現されているレコードを抜き出せる
SELECT * FROM Expenses
WHERE メモ  LIKE '%january%'

//ex2
//ESCAPEを書くことにより、$がエスケープ文字として認識され、エスケープ文字の直後の%や_は文字列として認識される（下記の例の場合january_3rdみたいな表記の検索ができる）
SELECT * FROM Expenses
WHERE メモ  LIKE '%january$_%' ESCAPE '$'
```

##間の検索：BETWEEN AND

```
式 BETWEEN 値1 AND 値2

//ex
//expenditureが100～3000のレコードを取得
SELECT *
FROM Expenses
WHERE expenditure BETWEEN 100 AND 3000
```

##計算式を含むSQL

```
//ex1
//expenditureと100円増しのexpenditureの列を表示
SELECT expenditure , expenditure + 100 AS　100円増しのexpenditure
FROM Expenses

//ex2
//すべてのexpenditureを100円足して更新
UPDATE Expenses
SET expenditure = expenditure + 100
```

##値を評価し好きな値へ変換：CASE WHEN THEN END

```
CASE 評価したい式や列 WHEN 値1 THEN 変える値1
(WHEN 値2 THEN 変える値2)
(ELSE デフォルト値)
END

//ex
//entryの値に応じて、housingとutilityはfixed costで、それ以外はvariable costとして表示する
SELECT entry, expenditure, 
CASE entry WHEN 'housing' THEN 'fixed cost'
WHEN utility THEN 'fixed cost'
ELSE 'variable cost'
END 
FROM Expenses WHERE expenditure >0
```




#検索結果の加工
##重複行の排除：DISTINCT
DISTINCTを使ってSELECTを行うと、重複がなくなるのでユニーク（一意）な値だけが表示されます

```
SELECT * DISTINCT income
FROM Expenses
```

##並べ替える：ORDER BY
SELECTの中身としては変わらないが、昇順・降順で並べ替えられます
ちなみに並べ替える列にNULL値があると、NULLは一番大きい値（昇順で一番下）として認識されるみたいです

```
ORDER BY 列名 並び順（下記参照）, 列名 並び順, ...（並列可能）
ASC：昇順（デフォルト）
DESC：降順（要指定）

//ex1
SELECT * FROM Expenses
//expenditureが降順で表示
ORDER BY income DESC, expenditure DESC

//ex2
SELECT * FROM Expenses
//列番号でも可
ORDER BY 4 DESC, 5 DESC
```

##出力する行数制限：LIMIT

```
SELECT * FROM Expenses
//上位3レコードのみ表示
ORDER BY income ASC LIMIT 3
```

##集合演算子：UNION, (EXCEPT, INTERSECTION)
UNIONであればSELECT文を和集合として表示でき、同様にEXCEPTは差集合、INTERSECTIONは積集合として表示できる
選択列のリストの列数とそれぞれのデータ型が同じでなければ使えない
UNION単体なら重複は削除、ALLのオプション付けると重複もすべて表示
EXCEPT, INTERSECTIONはmysqlでは使うことができない上、使い方が同じな為UNIONのみ紹介する

```
SELECT 文1
UNION オプション：ALL
SELECT 文2

//ex
SELECT * FROM Expenses
UNION ALL
SELECT * FROM ExpensesArchive
```

##計算式に別名を付ける：AS

```
//expenditureの列が出費という名前で表示される
SELECT expenditure AS 出費
FROM Expenses
```

#グループ化と集計関数
##集計関数：SUM, MAX, MIN, AVG, COUNT
SUM, MAX, MIN, AVG, COUNTは名前の通りそれぞれ合計、最大、最小、平均、行数のカウントを返します
COUNT(*)はNULLを行数としてカウントするのに対して、COUNT(列名)はNULLを行数としてカウントしない点に注意
そして基本的にこれの関数はSELCT文と後述のORDER BY, HAVINGの中だけで使え、WHEREなどでは使用できません

```
//ex1
SELECT SUM(expenditure) AS expenditureSum
FROM Expenses

//ex2
//Expensesの（NULLを含む）行数をrowCountとして出力
SELECT COUNT(*) AS rowCount
FROM Expeses
```

##グループ化：GROUP BY

```
SELECT 列や集計関数等
FROM テーブル名
(WHERE)
GROUP BY グループの基準列名

//ex
//entryをもとにグループ化が行われ、SUMの結果もentryごとに出力される
SELECT entry, SUM(expenditure)
FROM Expenses
GROUP BY entry
```

##グループ化したときの条件：HAVING
集計関数で述べたように、WHEREで集計関数はSQLの実行順序的に使えません（詳細はおまけの実行順序参照）
GROUP BYで集計したのち、その集計したものをさらに条件をかけたい場合にWHEREと同じ要領でHAVINGを使います

```
SELECT 列や集計関数等
FROM テーブル名
(WHERE)
GROUP BY グループの基準列名
HAVING 条件


//ex
//グループ化して、entry毎にexpenditureが1000以上の物のみ表示（絞り込み）
SELECT entry, SUM(expenditure)
FROM Expenses
GROUP BY entry
HAVING SUM(expenditure) => 1000
```

#テーブルの結合
##内部結合：JOIN ON
内部結合を行います（結合できるレコードがない時はすべて表示しない）

```
SELECT 選択列リスト
FROM テーブルA
JOIN テーブルB
ON 両テーブルの結合条件

//ex
SELECT DATE, NAME
FROM Expenses
JOIN Incomes
ON Expenses.ID = Incomes.ID
```

##外部結合：LEFT JOIN, RIGHT JOIN, FULL JOIN
LEFT JOIN：左外部結合（結合できるレコードがない時、左側のテーブルのみ全て表示して右側のテーブルは表示しない）
RIGHT JOIN：右外部結合（結合できるレコードがない時、右側のテーブルのみ全て表示して左側のテーブルは表示しない）
FULL JOIN：完全外部結合（結合できるレコードがない時としても全て表示）


```
//ex
SELECT DATE, NAME
FROM Expenses
LEFT JOIN Incomes
//左や右は=の左側か右側かで判断される
ON Expenses.ID = Incomes.ID
```


#便利な関数
##文字列
###文字数を数える：LENGTH
引数の文字列を出力

```
//ex
SELECT memo, LENGTH(memo) AS memo length
FROM Expenses
```

###文字列の余白を削除：TRIM
左右の余白を削除
LTRIM：左側の余白を削除
RTRIM：右側の余白を削除
使いどころとしては、CHAR(10)にabcと入力すると、右側に7個余白がついている状態になるので、主にそれを削除するために使われる

```
//ex
SELECT memo, TRIM(memo) AS trimmed memo
FROM Expenses
```

###文字列を置換：REPLACE

```
REPLACE(置換対象の列, 置換前の文字列, 置換後の文字列)

//ex
//この場合はメモ列に入っているbuyという文字列を買ったという文字列に置換している
UPDATE Expenses
SET memo = REPLACE(memo, 'buy', '買った')
```

###文字列の一部を抽出：SUBSTRING

```
SUBSTRING(文字列を表す列, 抽出を開始する位置, そこから抽出する文字数)

//ex
//entry列の1文字目から3文字を抜き出して、それが「～費」というパターンマッチに適合したレコードのみ表示する
SELECT * FROM Expenses
WHERE SUBSTRING(entry, 1, 3) LIKE '%費'
```


###文字列の結合：CONCAT, ||
純粋な文字列の結合は||だけでできますが、列同士で文字列の結合を行う場合はCONCATを使いましょう

```
CONCAT(文字列, 文字列 [, 文字列...])

//ex
//entry : memoの状態で列が結合される
SELECT CONCAT(entry, ' : ' || memo) 
FROM Expenses
```

##数値
###指定桁で四捨五入：ROUND

```
ROUND(四捨五入する数値, 有効桁数)
有効桁数：正の数は小数点以下の有効桁数、負の数は指定した分の下桁数

//ex
//-2は下2桁が四捨五入され、100円単位になる
SELECT expenditure,
ROUND (expenditure, -2) AS 百円単位の出金額
FROM Expenses
```

###指定桁で切り捨て：TRUNC
0を指定すると小数点以下切り捨てて、整数にできる
その他詳細は四捨五入と同じなので省略

```
TRUNC(切り捨てを行う数値, 有効桁数)
```

###べき乗を計算する：POWER

```
POWER(べき乗する数値, 何乗するか)

//ex
//expenditureを3乗する
POWER(expenditure, 3)
```

##その他
###副問い合わせを使って比較：ANY, ALL
比較演算子と組み合わせて、
ANY：値の中でいずれか1つでも真であれば真を返す
ALL：値の中ですべて真であれば真を返す

```
式　比較演算子　ANY/ALL (値1, 値2, ...)

//ex 
//副問い合わせを使い、5月のすべての出費（5月の一番高い買い物）よりも高い6月の出費を出力する
SELECT *
FROM Expenses
WHERE date >= '2021-06-01'
AND date <= '2021-06-30'
AND expenditure > ALL(
 SELECT expenditure FROM Expenses
 WHERE date >= '2021-05-01'
 AND date <= '2021-05-31')
```

###NULLの置き換えができる関数1：COALESCE
コアレスと読みます
行っている内容としては、引数を2つ以上取り、その中で最初にNULLではない値を取得するというものです
少し考え方を変えて、NULLがあったら次の引数を出力をするという書き方ができます(ex2参照)

```
//ex1
//下記コマンドを入力すると、「hello」という文字列が取得できます
COALESCE(NULL, NULL, NULL, 'hello', NULL)

//ex2
//今回はmemo列を指定し、もしmemoの内容がNULLであったら、NULLを出力する代わりに'NULLだよ'という文字列を出力できます
SELECT date, entry, COALESCE(memo, 'NULLだよ') AS memo
FROM 家計簿
```

###NULLの置き換えができる関数2：IFNULL
こちらの関数はシンプルで、1つ目に指定した引数がNULLであった場合、2つ目の引数が返されます
COALESCEと比べて使い関数の方を使えば良いと思います

```
//ex
//COALESCEのex2とまったく同じことをやっています
SELECT date, entry, IFNULL(memo, 'NULLだよ') AS memo
FROM 家計簿
```

###現在の日付や時間を得る：CURRENT_DATE, CURRENT_TIME

```
CURRENT_DATE：現在日付（YYYY-MM-DD）
CURRENT_TIME：現在の時刻（HH:MM::SS）

//ex
INSERT INTO Expenses
VALUES(CURRENT_DATE, 'food', 'donuts', 0, 260)
```

###データ型の変換：CAST

```
CAST(変換する値 AS 変換する型)

//ex
CAST(expenditure AS VARCHAR(20))
```



#おまけ
##実行順序
SQLは上から書いた順番に実行される訳ではなく、以下の順番で処理されます

1. FROM
1. WHERE
1. GROUP BY
1. HAVING
1. SELECT
1. ORDER BY

##扱っていないコマンドを軽く紹介
- OFFSET：先頭から指定行数除外
- FETCH：除外後何行出力するか
- EXIST：相関副問い合わせ