【新人教育 資料】第3章 SQLへの道 〜基本数学編〜

# 【新人教育 資料】第3章 SQLへの道 〜基本数学編〜
## あらすじ
新人がいっぱい入ってくる。新人のレベルもバラバラ。教育資料も古くなっているので、更新しましょう。
どうせなら、公開しちゃえばいいじゃん。という流れになり、新人教育用の資料を順次更新していくことにしました。

※後々、リクエストに応じて更新することが多いのでストックしておくことをおすすめします。

自分は[TEMONA株式会社](http://temona.co.jp/)でCTOをしていますが、頭でっかちに理論ばっかり学習するよりは、イメージがなんとなく掴めるように学習し、実践の中で知識を深めていく方が効率的に学習出来ると考えています。

※他の登壇やインタビュー記事は[Wantedly](https://www.wantedly.com/users/105935)から見てください。

教育スタイルとしては正しい事をきっちりかっちり教えるのではなく、未経験レベルの人がなんとなく掴めるように、資料を構成していきます。

以下のようなシリーズネタで進めます。

|No.|記事|
|:-----------|-----------|
|1|[【新人教育 資料】第1章 SQLへの道 〜DB編〜](http://qiita.com/devopsCoordinator/items/9b70e506150888e190be)|
|2|[【新人教育 資料】第2章 SQLへの道 〜3値論理編〜](http://qiita.com/devopsCoordinator/items/9c10410b50f8fcc2ba79)|
|3|[【新人教育 資料】第3章 SQLへの道 〜基本数学編〜](http://qiita.com/devopsCoordinator/items/08e405a9c58cc203d016)|
|4|[【新人教育 資料】第4章 SQLへの道 〜SQL基本操作編〜](http://qiita.com/devopsCoordinator/items/0f742158caf0fdb533e3)|
|5|[【新人教育 資料】第5章 SQLへの道 〜絞込編〜](http://qiita.com/devopsCoordinator/items/dca5aa9c155292f1c6ea)|
|6|[【新人教育 資料】第6章 SQLへの道 〜ソート編〜](http://qiita.com/devopsCoordinator/items/8cad032aa035dc1cdbc0)|
|7|[【新人教育 資料】第7章 SQLへの道 〜集合関数（SUM、MAX、MIN、AVG、COUNT）編〜](http://qiita.com/devopsCoordinator/items/85918c8508dddf19586f)|
|8|[【新人教育 資料】第8章 SQLへの道 〜グループ編〜](http://qiita.com/devopsCoordinator/items/f74228615982932c914b)|
|9|[【新人教育 資料】第9章 SQLへの道 〜結合編〜](http://qiita.com/devopsCoordinator/items/3ba154429973a4ddc9e0)|

では、今回もはじめていきましょう！

##四則演算
四則演算とは、みなさん小学校で習ったであろう+(足す),-(引く),*(かける：×),/(割る：÷)のことです。
若干算数や数学の時に使う記号と用いる文字が異なっていますが、そういうものと思ってください。
SQLで計算で四則演算することないじゃんって思う人もいると思いますが、演算子の優先順位なども分かりやすいので、ここでは紹介します。

SQLへの道ということでmysqlにて計算結果を見てみましょう。

###足す(15+5)

```
mysql> select 15+5 as result;
+--------+
| result |
+--------+
|     20 |
+--------+
```

###引く(15-5)

```
mysql> select 15-5 as result;
+--------+
| result |
+--------+
|     10 |
+--------+
```

###かける(15*5)

```
mysql> select 15*5 as result;
+--------+
| result |
+--------+
|     75 |
+--------+
```

###割る(15/5)

```
mysql> select 15/5 as result;
+--------+
| result |
+--------+
| 3.0000 |
+--------+
```

###四則演算の優先順位
四則演算には優先順位があります。【かける】と【割る】、は【足す】や【引く】より優先順位が高くなります。

```
【*】,【/】>【+】,【-】
```

####例：15+5*2-6/2

```
mysql> select 15+5*2-6/2 as result;
+---------+
| result  |
+---------+
| 22.0000 |
+---------+

```

【*】,【/】が優先して計算されるので15+10-3を計算することになります。【+】,【-】を優先して処理したい場合は()を用いて
優先順位を変更する事ができます。

```
mysql> select 15+5*(2-6)/2 as result;
+--------+
| result |
+--------+
| 5.0000 |
+--------+
```

この場合、カッコ内が先に計算されるので、15+5*(-4)/2という計算になります。
その他に結合法則、交換法則、分配法則と言った法則がありますが、それは各自勉強してください。
調べればすぐ「ああ、アレのことね」となると思います。後の節でこちらを前提に説明をするので、知らない人はチェックをしておいてください！

##順列,組み合わせ,確率
###順列、組み合わせ
順列や、組み合わせというのは、区別可能な複数のもの(元(げん)といいます)から特定の個数を取り出す事を言います。
その際に取り出す順番も加味するのを順列、取り出す順番は無視するのを組み合わせといいます。

読んでてよくわからないと思いますので図で説明をします。

![gen1.png](https://qiita-image-store.s3.amazonaws.com/0/104356/0f6a946a-af0e-82f8-81e5-27021248af92.png)
図１

図１のように、A~Gまでの７個の元からなる集合を考え、その中から特定の３個を取り出すことを考えます。
その場合、順列、組み合わせは下記のように考えます。

####順列のケース
全部書き出すと下記の210パターンが有ります。(スクリーンショットで載せておきますが多いですね。。)

![順列一覧.png](https://qiita-image-store.s3.amazonaws.com/0/104356/46962207-a750-bfbc-726e-5adb83ebdec1.png)
図２

これを一個一個数えていたのではあっという間に日が暮れてしまうので下記のように考えます。
これの考え方としては、
「最初に選ぶ文字としてA~Gの計7通りが有る。そして、最初の文字を選んだ後の次の文字の選び方として選ばれた以外の文字の6通りが有る。更に残った文字から選ぶ方法は５通り有る。」
というように考えて計算式は下記となります。

```
7*6*5=210
```
簡単ですね。これを順列(permutation)の頭文字をとって数学的には下記のように表現したりします。

${_7P_3}$


７個の元の集合から３個の元を取ってくる順列という意味になります。これを拡張して一般式として書くと下記となります。n個の元からr個を取ってきて並べる方法は下記の通りの数だけあります。

```
nPr =n*(n-1)*(n-2)*...(n-r+1)
```
####組み合わせのケース
組み合わせは順列の拡張版です。順列で取ってきたものから、順番を無視して重複しているものを消していけばいいのです。
先ほどの図２をもう一度見てみましょう。

例えば["A", "B", "C"]と重複しているもののは下記の5パターンになります。

```
["A", "C", "B"],["B", "A", "C"],["B", "C", "A"],["C", "A", "B"],["C", "B", "A"]
```
考え方はさっき覚えた順列を早速使って、3個の元の集合から３個を取り出す順列を考えればいいので

```
3P3 = 3*2*1 = 6通り
```
となります。上記のことからわかるように、全ての順列の一個一個に対して、6個の重複したものがあるので、組み合わせの個数としては

```
210/6 = 35通り
```
となります。こちらも組み合わせ(combination)の頭文字をとって下記の用に表現します。


${_7C_3}$

こちらを一般に拡張すると下記のようになります。n個の元からr個を取って来る組み合わせとなります。

```
nCr = (n * (n-1) * (n-2) * (n-3) *...(n-r+1))/(r * (r-1) * (r-2) * ...* 2 * 1)
```
見た目が若干いかつくなりましたが考え方を覚えていればそんなに難しくないですね！！

###確率
続いて確率です。「宝くじの当たる確率」とか日常でも使う言葉ですね。これを一般的に説明すると下記のようになります。

```
標本空間内において、特定の事象がどの程度起こるかを割合で表現したもの
```
難しいですね。宝くじの例で言うと

標本空間=全ての宝くじを引く
特定の事象=宝くじが当たるという出来事

ということになります。宝くじが100本、当たりが10本だとすると当たりを引くという事象は
100回引くうち10回起こるので

```
10/100 = 0.1
```
というように表現します。標本空間や特定の事象というのは当然ながら時と場合によって変わってきます。
さっきの順列・組み合わせのものを例を拡張して

```
A~Gまでの７個の元からなる集合を考え、その中から特定の３個を取り出した時、Aが含まれる確率は？
```
という場合は

```
標本空間 = A~Gの中から3個を取ってくる
特定の事象 = A~Gの中から3個を取ってきた中にAが入っている。
```
というようになります。

##論理式
###論理式とは
命題と呼ばれる式を論理演算記号によって結合された式のことを指します。

また難しい用語が出てきたので、１つずつ説明をしていきます。

- 命題：真(真実であるか)か偽(偽りであるか)を判定することが出来る文章のこと。

e.g)真の命題：りんごは果物である。　偽の命題：犬は果物である。

- 論理演算記号：以下の演算記号があります。
 - ¬： 否定(文字通り否定です。集合では<ruby>　<rp>（</rp><rt>＿</rt><rp>）</rp></ruby>と表されます。)
 - ∨ ： 論理和(又は、orと同じ意味。集合では∪と表されます。)
 - ∧ ： 論理積(且つ、andと同じ意味。集合では∩と表されます。)
 - ⇒ ： 含意(含まれることを表します。集合では⊂と表されます。)
 - ⇔ ： 同値(同じであることを表します。集合では=と表されます。)

具体例を上げて考えてみましょう。

命題A：りんごは果物です。(真)
命題B：東京は日本の首都です。(真)
命題C：京都は日本の首都です。(偽)
命題D：紅玉は果物です。（真）

上記の命題の場合、論理演算子を使うと下記のようになります。

- ¬A：「バナナは果物ではない」となり、¬Aは「偽」となります。Aと真偽が入れ替わります。

- B∨C：「東京は日本の首都です。」又は「京都は日本の首都です。」となり、全体としては「真」となります。少なくとも片方が「真」であれば全体として真となります。

- B∧C：「東京は日本の首都です。」且つ「京都は日本の首都です。」は、「偽」となります。

- D⇒A：「紅玉は果物です。」は「りんごは果物です。」という命題に包含されている(りんごが果物なら、りんごの種類の紅玉も当然果物)ので、こちらは「真」となります。

- A⇔A：「りんごは果物です。」は「りんごは果物です。」と同値(同じもの)であるため「真」となります。


##ベン図とオイラー図
###ベン図とは
図を見ればああ、あれねとなるやつです。上の論理式を集合に援用した内容が説明に出てきます。

![ベン図.png](https://qiita-image-store.s3.amazonaws.com/0/104356/e33cc2ef-5684-3690-a467-ed69beb23647.png)
図3

上記の図の意味としては
Ω：全体集合（文字通り森羅万象全てを含む集合）
A：集合A
B：集合B

という意味になります。それぞれの集合の中には先程述べた元がいくつか入っている事になります。
この時図の(1)~(3)の集合部分を前節で取り上げた論理式の考え方を使って表現していきます。
 
(1)：集合Aであり、且つBでない集合　⇒　A∩<ruby>B<rp>（</rp><rt>＿</rt><rp>）</rp></ruby>
(2)：集合Aであり、且つBでもある集合　⇒　A∩B
(3)：集合Bであり、且つAでない集合　⇒　B∩<ruby>A<rp></rp><rt>＿</rt><rp></rp></ruby>
その他空白の部分：集合Aでない、且つBでない集合　⇒　<ruby>A<rp>（</rp><rt>＿</rt><rp>）</rp></ruby>∩<ruby>B<rp>（</rp><rt>＿</rt><rp>）</rp></ruby>

記号の意味を説明します。
∩：「且つ」を表します。論理積に近いものとなります。
∪：「又は」を表します。論理和に近いものとなります。
<ruby>　<rp>（</rp><rt>＿</rt><rp>）</rp></ruby>：「否定」を表します。

論理式は「真」、「偽」の二通りしかありえないのに対して、集合だと元は複数持つことができるので、そこの部分で多少の差異が出てきますね。

###オイラー図とは
ベン図の発展的な内容も含んでいるのがオイラー図となります。
先ほどの説明だと記号として「且つ」、「又は」、「否定」しか出てきませんでした。
論理式で出た包含、同値の概念も組み入れられた図も含めたベン図をオイラー図といいます。

ちなみに集合Aが集合Bに含まれるという場合や同値という場合、先程も言ったとおり、集合では

A ⊂ B　、　A = B

と表します。

##ド・モルガンの定理
下記の公式のことを言います。上の図３を例にとって考えましょう。

（１）<ruby>(A∩B)<rp>（</rp><rt>＿＿＿＿</rt><rp>）</rp></ruby>　= <ruby>A<rp>（</rp><rt>＿</rt><rp>）</rp></ruby> ∪ <ruby>B<rp>（</rp><rt>＿</rt><rp>）</rp></ruby>

（２）<ruby>(A∪B)<rp>（</rp><rt>＿＿＿＿</rt><rp>）</rp></ruby>　= <ruby>A<rp>（</rp><rt>＿</rt><rp>）</rp></ruby> ∩ <ruby>B<rp>（</rp><rt>＿</rt><rp>）</rp></ruby>

（１）から説明していきましょう。
左辺はすぐにイメージが出来ると思います。図示するとこうなります。

![且つの否定.png](https://qiita-image-store.s3.amazonaws.com/0/104356/621e03a5-a514-8467-b117-f9cfb0883585.png)
図4

重なっている所(A∩B)以外全てという状態です。

右辺も結果左辺とおなじになるんですが、分解して説明していきましょう。
まず<ruby>A<rp>（</rp><rt>＿</rt><rp>）</rp></ruby>を図示します。

![Aでない.png](https://qiita-image-store.s3.amazonaws.com/0/104356/a537e422-664e-1930-69c7-b678326ef85f.png)
図5

グレーの部分ですね。
続いて<ruby>B<rp>（</rp><rt>＿</rt><rp>）</rp></ruby>も図示します。

![Bでない.png](https://qiita-image-store.s3.amazonaws.com/0/104356/d4b9285e-a626-45d3-df1c-fec1eb248392.png)
図6

<ruby>A<rp>（</rp><rt>＿</rt><rp>）</rp></ruby>と<ruby>B<rp>（</rp><rt>＿</rt><rp>）</rp></ruby>は∪で繋がれているので、２つの図のグレー部分を足し合わせます。
すると最初の図と一緒になりますよね。

（２）についても考え方は同じですね。最後が足すのでは無く、共通部分を持ってくるというところが違うだけです。分解して考えればすぐわかると思います。

上記は２つの集合のケースで証明しましたが、ここからn個の集合に拡張した場合も簡単に証明ができます。興味有る方は調べてみてください。


次で漸く最後の項目です。あと少しなので頑張りましょう
##ブール代数、カルノー図
また新しい言葉が出てきましたね。役割としては上記で出たベン図などを表した式や論理式を簡単にするために用いる概念になります。順番に説明していきますね。

###ブール代数
まずブール代数の前提を説明致します。

- 演算子は「+」、「・」、「<ruby>　<rp>（</rp><rt>＿</rt><rp>）</rp></ruby>」の３つになります。それぞれ「足す(加法)」、「かける（乗法）」、「否定」の意味になります。

- 値として0,1しか存在しません。

この前提のもとで、以下の法則が成り立ちます。(証明は各自でやってみてください。)

|法則名|法則１|法則２|
|:-----|-----|-----|
|交換法則|A + B = B + A|A・B = B・A|
|分配法則|A・(B+C)=(A・B) + (A・C)|A + (B・C)=(A+B)・(A+C)|
|単位元|A + 0 = A|A・1 = A|
|補元|A + <ruby>A<rp>（</rp><rt>＿</rt><rp>）</rp></ruby> = 1|A・<ruby>A<rp>（</rp><rt>＿</rt><rp>）</rp></ruby> = 0|

一番最初の四則演算の節の最後で触れた法則に法則１は似ていますが、法則２の分配法則が少し直感的ではないかもしれません。
実はブール代数には「双対の原理」というものが成り立っていて、それを知っていると法則２は法則１を覚えているだけで導き出すことが出来ます。

```
(双対の原理)ブール代数では、加法と乗法、1と0を同時に入れ替えても
入れ替える前の等式が成立していれば、入れ替え後の等式も成立する。
```

法則２は全て法則１の双対となっています。
この0と1というのが先ほど論理式で使った「偽」、「真」と対になっています。「加法」は論理和、「乗法」は論理積に対応しています。
上記の法則を使えば複雑になってしまった論理式を簡単にすることが出来ます。

###カルノー図
先ほどのブール代数は式として簡略化するアプローチでしたがこちらは図から論理式を簡略化するアプローチです。

言葉で説明するより例を実際に用いるほうがわかりやすいので、いきなり例題に行きます。

例題)A・B・<ruby>C<rp>（</rp><rt>＿</rt><rp>）</rp></ruby> + A・B・C
の論理式を簡単にせよ。

ぱっと見ると複雑ですよね。これをカルノー図にすると下記の表になります。
![カルノー図その１.png](https://qiita-image-store.s3.amazonaws.com/0/104356/0b926932-a0b0-69cd-47c2-396ef70f5d51.png)
図7

行(縦)がCの真偽値を表していて、列(横)がABの真偽値の組み合わせを表しています。
1が「真」で0が「偽」です。

この時図の(1)に入っている1で表現されているのが「A・B・<ruby>C<rp>（</rp><rt>＿</rt><rp>）</rp></ruby>」の部分になります。同じく(2)に入っている１が「A・B・C」と対になります。この２つをあわせた(3)が上の論理式で表されたものとなります。
これをじっくり見てもらうと上記の論理式はCの真偽に関係していないことがわかり、

```
A・B
```

と同値であることがわかると思います。これをブール代数を使ってやるとちょっと手間になります。


A・B・<ruby>C<rp>（</rp><rt>＿</rt><rp>）</rp></ruby> + A・B・C
→分配法則
A・B・(<ruby>C<rp>（</rp><rt>＿</rt><rp>）</rp></ruby> + C)
→補元
A・B・1
→単位元
A・B

数式に抵抗がなければブール代数、そうでなければカルノー図がおすすめっといったところでしょうか？
後カルノー図の欠点としては変数が増えすぎると表がものすごく大きくなってしまうところです。

## あとがき
いかがでしたでしょうか？今回はSQLと直接関係が有るところではなかったですが、この考え方はプログラム開発の全ての基礎の部分となるので、後から振り返って見てみるのもいいかもしれません。