SQL入門のまとめ①(検索結界の加工,集合演算子について)

# はじめに
数日前から「[スッキリわかるSQL入門 第2版](https://www.amazon.co.jp/%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8BSQL%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E3%83%89%E3%83%AA%E3%83%AB222%E5%95%8F%E4%BB%98%E3%81%8D-%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E4%B8%AD%E5%B1%B1%E6%B8%85%E5%96%AC/dp/4295005096)」という書籍で勉強するようになり、勉強会で一章ずつ発表する機会をいただいたので、勉強したことのアウトプットとして記事を書こうと思いました。
この書籍では、「dokoQL」というDBMSの導入や設定をすることなく簡単にSQLを実行できるサービスを使います。
テーブルには「家計簿」が取り上げられていて、とても身近でわかりやすく書かれています。
今回は第1部の四章から始めます。

# 検索結果の加工
今回はSELECT文だけにつけることができる修飾語を紹介していこうと思います。

# DISTINCT(重複した行を取り除く)
>
SELECT 入金額　FROM 家計簿

これを実行すると、家計簿テーブルから入金額のカラムが全て表示されます。

>
SELECT DISTINCT 入金額　FROM 家計簿

今度はDISTINCTを使って実行しました。すると同じ入金額の部分の表示がなくなります。

# ORDER BY(並べ替える)
```sql
SELECT 列名(カラム名)　FROM テーブル名
　　ORDER BY 列名(カラム名) 並び順
```
並び順は昇順にするときはASC,降順にするときはDESCを使います。
初期値は昇順になっており、省略すると結果は昇順になります。

```sql
SELECT * FROM 家計簿
　　ORDER BY 出金額
```
これを実行すると以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1403010/52940139-0dee-8a11-5c2f-1da465fb63cf.png)

今度は降順にしてみます。

```sql
SELECT * FROM 家計簿
　　ORDER BY 出金額 DESC
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1403010/93d490a8-e99c-ae46-c0b1-b5ab69d05476.png)

出金額に注目すると、降順になっているのがわかります。

また、ORDER BY句では複数の列を指定して並び替えることもできます。
例として、入金額を昇順で並べるが、入金額が等しい行については出金額を昇順で並べてみます。

```sql
SELECT * FROM 家計簿
 ORDER BY 入金額 ASC, 出金額 ASC
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1403010/e9b3e564-50e8-a57b-3f2c-0e0721352921.png)

# OFFSET-FETCH(行の一部を取得)
OFFSET-FETCHは検索結果の全ての行ではなく、一部の行が欲しいときに使うと便利です。

```sql
SELECT 列名(カラム名) FROM テーブル名
 ORDER BY 列名(カラム名)
OFFSET 先頭から除外する行数　ROWS
FETCH NEXT 表示する行数　ROWS ONLY
```
先頭から除外する行数は必ず、記述しないといけないので除外する必要がない場合は0と書きます。

```sql
SELECT 費目, 出金額 FROM 家計簿
 ORDER BY 出金額 DESC
OFFSET 0 ROWS
 FETCH NEXT 3 ROWS ONLY
```
この場合の結果は以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1403010/b8dfbe4e-a26b-cffa-bc11-2b42f65926a1.png)

家計簿テーブルから費目と出金額の列名を取り出し、出金額を降順に並べます。
その際、先頭から除去する行数が0なので最初の行から取得します。そして表示する行数が３なのでこのような結果になります。

# 集合演算子
ずっとデータベースを使用していると、テーブルの行数などが多くなり処理が遅くなってしまいます。
それを防ぐために今までのデータを別のテーブルに分けて管理することにします。
複数のテーブルの結果同士を足したり、共通部分を探したりするのに集合演算子を使います。
SQLでは3つの集合演算子を使うことができます。

# UNION(和集合を返す)
2つのSELECT文をUNIONを使って繋げると、それぞれの結果を足し合わせることができます。

```sql
SELECT 文A
 UNION (ALL)
SELECT 文B
```
UNIONだけだと重複文を一行にまとめて表示しますが、ALLをつけると重複行を全て表示することができます。

# EXCEPT/MINUS(差集合を返す)
差集合は文字通り、ある集合と他の集合の差を表します。ちなみにOracle DBではEXCEPTの代わりにMINUSを使います。

```sql
SELECT 文A
 EXCEPT (ALL)
SELECT 文B
```
EXCEPT ALLはUNIONの場合と同様に重複行を全て表示させます。
和集合ではどちらのSELECT文が先でも結果は同じですが、差集合では基準となる集合によって結果が異なるので注意が必要です。

# INTERSECT(積集合を返す)
積集合は2つの検索結果で重複するものを表示させます。
積集合を求めるには次のように書きます。

```sql
SELECT 列名(カラム名) FROM テーブル名
INTERSECT (ALL)
SELECT 列名(カラム名) FROM テーブル名
```
積集合は和集合と同じで、SELECT文の順序を変えても結果は変わりません。
また、INTERSECT ALL とすると積集合から重複行が取り除かれます。

# 集合演算子を使う条件
集合演算子を使ってまとめるときには、列数とデーター型が一致していなければならないという決まりがあります。
列数とデータ型が一致していれば異なるテーブルや列でもまとめることができます。

# まとめ

DISTINCT :重複行を取り除く
ORDER BY :検索結果を並び替える
OFFSET FETCH :行を指定して取得する
UNION,EXCEPT/MINUS,INTERSECT :検索結果を集合演算する

* 集合演算子
  - UNIONは和集合を求める
  - EXCEPT,MINUSは差集合を求める
  - INTERSECTは積集合を求める
 
# 参考文献
書籍『スッキリわかるSQL入門第2版ドリル222問付き！』