SQLの基礎について学ぶ＃０５


今回は検索結果の加工を用いた操作する行の絞り込みについて、まとめていきたいと思います。
### 過去の関連投稿
「[SQLの基礎について学ぶ＃０１](https://qiita.com/TAISEI-050523/items/31dd74cd386fe4dc46bf "Qiita")」
「[SQLの基礎について学ぶ＃０２](https://qiita.com/TAISEI-050523/items/75265fba015879bd3bf8 "Qiita")」
「[SQLの基礎について学ぶ＃０３](https://qiita.com/TAISEI-050523/items/2d87b30fa3de353af159 "Qiita")」
「[SQLの基礎について学ぶ＃０４](https://qiita.com/TAISEI-050523/items/6c4509276613d5eee488 "Qiita")」

## 1. 検索結果の加工
###４大命令の復習
|    命令    |    各命令の固有部分      |    対象行の絞り込み     |検索結果の加工|
|:-----------:|:------------:|:------------:|:------------:|
| SELECT |　列名 FROM テーブル名  　 | WEHERE~         |その他の修飾
| UPDATE |　テーブル名 SET 列名 = 値 　 | WEHERE~         |
| DELETE |　FROM テーブル名  　 | WEHERE~ |
| INSERT |　INTO テーブル名(列名) VALUES(値) |  |
　上の表で示したように<B>検索結果の加工</B>は<B>SELECT文</B>に用います。
今回は３つの<B>検索結果</B>を加工するキワードを見ていきます。

### 検索結果を加工するキーワード
|    キーワード    |    説 明       | 
|:-----------:|:------------:|
| DISTINCT |　検索結果から重複する行を除外する  　 | 
| ORDER BY |　検索結果の順序を並び替える 　 | 
| OFFSET-FETCH |　検索結果から件数を限定して取得する | 

## 2. DISTINCT 重複行を除外する
<B>DISTINCT</B>をSELECT文に付けることで、検索結果表の中で重複する行があれば、重複している行を取り除きます。
次のテーブルを用いて説明していきます。
###accountテーブル
|    price（金額）     |
|:------------:|
| 100         |
| 2000         |
| 1000         |
| 2000         |
| 100         |
| 1000         |

```SQL
SELECT DISTINCT price FROM account
```
###検索結果
|    price（金額）     |
|:------------:|
| 100         |
| 2000         |
| 1000         |
このように、重複している金額が除外されました。
これだけだとイメージしにくいので、これを２段階に分けて説明します。まず

```SQL
SELECT /* DISTINCT */ price FROM account
```
によって、検索結果①が取得できます。
###検索結果①
|    price（金額）     |
|:------------:|
| 100         |
| 2000         |
| 1000         |
| 2000         |
| 100         |
| 1000         |
そして、<B>DISTINCT</B>によって、検索結果①から重複している金額を除外して、検索結果②が取得できます。
###検索結果②
|    price（金額）     |
|:------------:|
| 100         |
| 2000         |
| 1000         |
このように、<B>検索結果の加工</B>は<B>２段階</B>でイメージすると分かりやすいかなと私は感じました。

## 2. ORDER BY 結果を並べ替える
SELECT文に<B>ORDER BY</B>を付けることで、指定した列を基準として、検索結果を並び替えて取得することができます。
それでは、次のテーブルを使用して説明していきます。
###accountテーブル
|    date（日付）    |    name（項目名）       |    price（金額）     |
|:-----------:|:------------:|:------------:|
| 2020-12-14 |　お茶  　 | 1000         |
| 2020-12-03 |　お弁当 　 | 3000         |
| 2021-01-11 |　電車代  　 | 2500         |
| 2020-12-16 |　ラーメン 　 | 100         |
| 2021-01-04 |　日用品  　 | 2000         |

まず金額で<b>降順（大きいもの順）</b>になるように並べ替えます。

```SQL
SELECT * FROM account
 ORDER BY price DESC /* DESCで降順指定*/
```
###結果
|    date（日付）    |    name（項目名）       |    price（金額）     |
|:-----------:|:------------:|:------------:|
| 2020-12-03 |　お弁当 　 | 3000         |
| 2021-01-11 |　電車代  　 | 2500         |
| 2021-01-04 |　日用品  　 | 2000         |
| 2020-12-16 |　ラーメン 　 | 600         |
| 2020-12-14 |　お茶  　 | 100         |

次に金額で<b>昇順（小さいもの順）</b>になるように並べ替えます。

```SQL
SELECT * FROM account
 ORDER BY price ASC /* ASCで昇順指定*/
```
###結果
|    date（日付）    |    name（項目名）       |    price（金額）     |
|:-----------:|:------------:|:------------:|
| 2020-12-14 |　お茶  　 | 100         |
| 2020-12-16 |　ラーメン 　 | 600         |
| 2021-01-04 |　日用品  　 | 2000         |
| 2021-01-11 |　電車代  　 | 2500         |
| 2020-12-03 |　お弁当 　 | 3000         |

## 3. OFFSET-FETCH 先頭から指定した行数だけを取得する
検索結果の全ての行だけでなく、例えば「金額が高い項目トップ３」など一部の行だけ取得したい場合に<B>OFFSET-FETCH</B>を用います。

```SQL
/* 先頭の数件だけを取得する */
SELECT 列名 FROM テーブル名
  ORDER BY 列名
 OFFSET 先頭から除外する行数 ROWS
  FETCH NEXT 取得する行数 ROWS ONLY
/* MySQL, MariaDB, SQLiteではサポートされていないため、この場合、LIMITを使用する */
```
それでは、次のテーブルを使用して説明していきます。
###accountテーブル
|    date（日付）    |    name（項目名）       |    price（金額）     |
|:-----------:|:------------:|:------------:|
| 2020-12-14 |　お茶  　 | 1000         |
| 2020-12-03 |　お弁当 　 | 3000         |
| 2021-01-11 |　電車代  　 | 2500         |
| 2020-12-16 |　ラーメン 　 | 100         |
| 2021-01-04 |　日用品  　 | 2000         |

```SQL
/* 金額の高い順に３件取得する */
SELECT name, price FROM account
  ORDER BY price DESC
 OFFSET 0 ROWS
  FETCH NEXT 3 ROWS ONLY
```
###結果
|    name（項目名）       |    price（金額）     |
|:------------:|:------------:|
|　お弁当 　 | 3000         |
|　電車代  　 | 2500         |
|　日用品  　 | 2000         |

```SQL
/* ３番目に高い金額を取得する */
SELECT name, price FROM account
  ORDER BY price DESC
 OFFSET 2 ROWS
  FETCH NEXT 3 ROWS ONLY
```
###結果
|    name（項目名）       |    price（金額）     |
|:------------:|:------------:|
|　日用品  　 | 2000         |
###取得行を限定するその他の方法
<b>LIMIT</b>の使用

```SQL
/* MySQL, MariaDB, SQLite, PostgreSQL, H2などで使用 */
/* 金額の高い順に３件取得する */
SELECT name, price FROM account
ORDER BY price DESC LIMIT 3
```
　この投稿では紹介しませんが、その他<b>ROW_NUMBER</b>や<b>ROWNUM</b>などがあります。また、これらは使用するDBMSによって利用できる範囲が異なります。


# まとめ
　<B>SELECT文</B>に<B>ORDER BY</B>を用いることで簡単に<B>並び替えの処理</B>を行うことができました。しかし、この並び替えの処理は<B>DBMS</B>にとって、かなり負担の大きい作業です。便利な機能でもDBMSへの負担を考慮しながら、データベースを扱えるように今後もSQLの学習を進めていきたいと思います！！