～未経験・知識なしからセキュリティ(デフ)エンジニアになる人！～『{Level10}MySQL > 』

こんにちは、itoshinです。
前回投稿から間が空いてしまいました...。
言い訳すると、季節の変わり目などによる日照時間や気温の変化に弱く、体調崩していました。
~~（ほぼ毎年か2年毎くらいに高確率で胃腸炎や消化不良になったりする時期...（笑））~~
こういう時は夏の疲れや体質変化を起こしているので、回復を優先した方が良いですね。
内臓を冷やさないよう16時間ほど断食したら少し調子が回復してきました！
あとは習慣付けたいもの（Qiitaや資格勉強）を再開しやすいよう最初のハードルを下げていきましょう。

さて、前回はデータベースの基本的な操作に触れていきました。
今日は知っておいた方がより効率や視認性が上がる操作構文を学んでいきましょう！

### レコードの並び替え（ソート）
データが沢山収集されてくると、どうしても見にくくなります。
レコードの絞り込みをしても良いですが、全てのレコードを並べ替えて把握したい時がきっとあるはずです。
↓条件指定せず、表示するとプライマリーキーに設定されているuid順に表示される
```
 select * from schedule;
+-----+---------+-----------------+------------+----------+------+------------------+
| pid | uid     | subject         | pdate      | ptime    | cid  | memo             |
+-----+---------+-----------------+------------+----------+------+------------------+
|   1 | yyamada | WINGS会議       | 2018-06-25 | 15:00:00 |    1 | 配布プリント持参 |
|   2 | tsatou  | B企画書提出     | 2018-07-05 | 17:00:00 |    3 | サンプル添付     |
|   3 | yyamada | MySQL本原稿提出 | 2018-07-31 | 17:00:00 |    3 | NULL             |
|   4 | yyamada | WINGSメンバ面接 | 2018-08-05 | 13:00:00 |    5 | NULL             |
|   5 | nkakeya | WINGS会議       | 2018-06-25 | 14:00:00 |    1 | 事前に会場準備   |
|   6 | nkakeya | C社打ち合わせ   | 2018-07-31 | 14:00:00 |    2 | NULL             |
|   7 | ssuzuki | WINGS会議       | 2018-06-25 | 15:00:00 |    1 | ファイル持参     |
|   8 | hinoue  | 小学校参観日    | 2018-08-10 | 14:00:00 |    4 | NULL             |
|   9 | yyamada | D企画打ち上げ   | 2018-08-21 | 18:00:00 |    5 | NULL             |
|  10 | nkakeya | D企画打ち上げ   | 2018-08-21 | 18:00:00 |    5 | 出席者確認       |
|  11 | yyamada | wings会議       | 2023-06-25 | 15:00:00 |    1 | 配布プリント持参 |
+-----+---------+-----------------+------------+----------+------+------------------+
11 rows in set (0.04 sec)
```
上の羅列ではいつ何があって、開催時刻を瞬時に確認するのがめんどくさい上に、見間違いなどのヒューマンエラーが起きそうです。

なので、並べ替え（ソート）して視認性を上げましょう。↓
``select uid, subject, pdate, ptime from schedule``
``order by pdate ASC, ptime ASC;``
[scheduleテーブルのuid,suject,pdate,ptimeを表示し、pdateとptimeを昇順に並べ替えて]

構文[select~order by~]
``select フィールド名, ...from テーブル名 order by　ソート条件``
```
select uid, subject, pdate, ptime from schedule
order by pdate ASC, ptime ASC;
+---------+-----------------+------------+----------+
| uid     | subject         | pdate      | ptime    |
+---------+-----------------+------------+----------+
| nkakeya | WINGS会議       | 2018-06-25 | 14:00:00 |
| yyamada | WINGS会議       | 2018-06-25 | 15:00:00 |
| ssuzuki | WINGS会議       | 2018-06-25 | 15:00:00 |
| tsatou  | B企画書提出     | 2018-07-05 | 17:00:00 |
| nkakeya | C社打ち合わせ   | 2018-07-31 | 14:00:00 |
| yyamada | MySQL本原稿提出 | 2018-07-31 | 17:00:00 |
| yyamada | WINGSメンバ面接 | 2018-08-05 | 13:00:00 |
| hinoue  | 小学校参観日    | 2018-08-10 | 14:00:00 |
| yyamada | D企画打ち上げ   | 2018-08-21 | 18:00:00 |
| nkakeya | D企画打ち上げ   | 2018-08-21 | 18:00:00 |
| yyamada | wings会議       | 2023-06-25 | 15:00:00 |
+---------+-----------------+------------+----------+
11 rows in set (0.00 sec)
```
↑開催日時が古い順（昇順）にソートされ、予定の確認がしやすくなりました。
新しい順（降順）で指定する場合はDESC（値が大きい順）でソートすればヨシ！

:::note alert
注意！
並べ替えるフィールドのデータ型は文字列ではなく、数値データ型を設定しておきましょう。正確にソートされなくなります。
:::
### 特定範囲のレコード抽出
前項でソートした結果から上位〇件目までを取り出したりできれば、直近の予定のみを表示したり、商品を扱うレコードであれば売れ行きの良いTop10だけをアピールすることもできるでしょう。
その場合はselect~order by構文にlimit句を加えることで、レコード範囲を制限します。
``select uid, subject , pdate, ptime, memo from schedule``
``order by pdate , ptime limit 5;``
[scheduleテーブルのuid,subject,pdate,ptime,memoを、pdateとptimeの順で並べ替えた先頭の５件だけを表示して]

構文
``select フィールド名, ...from テーブル名 order by ソート条件 limit （開始行,）行数``
```
mysql> select uid, subject , pdate, ptime, memo from schedule
    -> order by pdate , ptime limit 5;
+---------+---------------+------------+----------+------------------+
| uid     | subject       | pdate      | ptime    | memo             |
+---------+---------------+------------+----------+------------------+
| nkakeya | WINGS会議     | 2018-06-25 | 14:00:00 | 事前に会場準備   |
| yyamada | WINGS会議     | 2018-06-25 | 15:00:00 | 配布プリント持参 |
| ssuzuki | WINGS会議     | 2018-06-25 | 15:00:00 | ファイル持参     |
| tsatou  | B企画書提出   | 2018-07-05 | 17:00:00 | サンプル添付     |
| nkakeya | C社打ち合わせ | 2018-07-31 | 14:00:00 | NULL             |
+---------+---------------+------------+----------+------------------+
5 rows in set (0.00 sec)
```
### レコードの集計（グループ化と集計関数）
それぞれのメンバーがいくつ予定を組んでるかを知りたい時、一覧を表示して数えるのは大変な場合があるでしょう。
そんな時はレコードをグループ化して集計することでシンプルに把握することが可能です。
``select uid, count(*) from schedule``
``group by uid;``
[scheduleテーブルのuidをグループ化し、それぞれの件数を表示して]

構文
``select フィールド名, ..., 集計式, ...from テーブル名 group by　グループキー``
```
mysql> select uid, count(*) from schedule
    -> group by uid;
+---------+----------+
| uid     | count(*) |
+---------+----------+
| hinoue  |        1 |
| nkakeya |        3 |
| ssuzuki |        1 |
| tsatou  |        1 |
| yyamada |        4 |
+---------+----------+
5 rows in set (0.02 sec)
```
↑なお、count関数は指定したフィールドの「NULLでない件数」のみを集計するため、NULLが含まれるフィールドを無条件にカウントする場合は「*」か主キー列を指定しましょう。
↓その他の集計関数
| 関数 | 求める値 |
|:-:|:-:|
| AVG（フィールド名） | 平均値  |
| COUNT（フィールド名）  | 件数  |
| MAX（フィールド名）  | 最大値  |
| MIN（フィールド名）  | 最小値  |
| SUM（フィールド名）  | 合計値  |


### (集計した)フィールドの別名設定
関数や演算子でフィールドを加工して表示した場合、前項のCOUNT(*)のようなフィールド名で出力されてしまいます。
長めの式となった時は特に分かりにくい項目になってしまうため、別名を付けるのが一般的なようです。
``select max(family) as 最大,``
``min(family) as 最小,``
``avg(family) as 平均 from usr;``
[usrテーブルのfamily数のmaxを"最大"に改名]
[minを"最小"に改名]
[avgを"平均"に改名し、表示して]

構文
``select フィールド名 as 別名, ...from テーブル名 [where句など]``
```
mysql> select max(family) as 最大,
    -> min(family) as 最小,
    -> avg(family) as 平均 from usr;
+------+------+--------+
| 最大 | 最小 | 平均   |
+------+------+--------+
|    5 |    1 | 3.5000 |
+------+------+--------+
1 row in set (0.00 sec)
```

フィールドの別名を付けるついでにselect命令文で取得した値は算術演算子（加減乗除する）を用いて演算させることができます。
``select uid, uname, family -1 as 家族数 from usr;``
[usrテーブルのuid,uname,family（別名を家族数に、本人分を引いた値に）を表示して]
```
mysql> select uid, uname, family -1 as 家族数 from usr;
+---------+----------+--------+
| uid     | uname    | 家族数 |
+---------+----------+--------+
| hinoue  | 井上花子 |      3 |
| mtanaka | 田中美紀 |   NULL |
| nharada | 原田直樹 |      2 |
| nkakeya | 掛谷奈美 |      4 |
| ssuzuki | 鈴木正一 |      3 |
| tsatou  | 佐藤留吉 |      0 |
| yyamada | 山田祥寛 |      3 |
+---------+----------+--------+
7 rows in set (0.00 sec)

```
### 関数（日付の表示形式を変更）
関数を用いることで、形式的な表示が容易になります。
関数とは何らかの値（引数またはパラメータ）を与えることで、予め決められた処理を行い、その結果（戻り値）を返す仕組みです。
``select subject as 件名,``
``date_format(pdate, '%y年%m月%d日') as 予定日,``
``ptime as 予定時刻 from schedule``
``where uid = 'yyamada';``
[schduleテーブルからuidが"yyamada"の]
[件名（元subject）、予定日（元pdate,表示形式にdate_format関数使用）、予定時刻（元ptime）を表示して]

構文
``関数名（引数, 引数, ...）``
```
mysql> select subject as 件名,
    -> date_format(pdate, '%y年%m月%d日') as 予定日,
    -> ptime as 予定時刻 from schedule
    -> where uid = 'yyamada';
+-----------------+--------------+----------+
| 件名            | 予定日       | 予定時刻 |
+-----------------+--------------+----------+
| WINGS会議       | 18年06月25日 | 15:00:00 |
| MySQL本原稿提出 | 18年07月31日 | 17:00:00 |
| WINGSメンバ面接 | 18年08月05日 | 13:00:00 |
| D企画打ち上げ   | 18年08月21日 | 18:00:00 |
+-----------------+--------------+----------+
4 rows in set (0.01 sec)

```
### 関数（平均値を四捨五入して求める）
また、平均値を四捨五入する関数もあります。
``select round(avg(family)) as 平均家族数 from usr;``
[usrテーブルから平均家族数（元familyの値を平均し、四捨五入）を表示して]
```
mysql> select round(avg(family)) as 平均家族数 from usr;
+------------+
| 平均家族数 |
+------------+
|          4 |
+------------+
1 row in set (0.00 sec)
```

今夜はここまで！