SQL SELECT基礎(1) データと表

この記事は「SQL SELECT基礎」の第1回目です。
[SQL SELECT基礎 目次](http://qiita.com/Hiraku/items/67cf329f1ddb897b1436)
→次の記事は[SQL SELECT基礎(2) スカラ値いろいろ](http://qiita.com/Hiraku/items/2bf26e8cdf117a7f81e8)

## データと表

> 検索や蓄積が容易にできるよう整理された情報の集まり。 
[データベース - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9)

超巨大なデータを、どのような概念で扱うべきか。色々なモデルが考案されてきましたが、主流の1つとしてリレーショナルデータベース(RDB)というものがあります。

SQLはこのタイプのデータベースで使われる、データを作成したり抽出するための言語です。

昨今はSQLを学べば、様々な製品を使いこなせるようになりました。実装がRDBとは言えなくても、SQLが使える製品が非常にたくさんあります。

小さなデータであれば、手元にコピーして全件見ていってもよいでしょう。Excelにまとめられた住所録なんかが良い例です。

しかしデータが数GBになったら？ データが常に追加されている状況だったら？ Excelで収まる限界のデータ量もありますし、そのうちコピーするだけで時間がかかるようになります。効率的ではありません。

SQLは「どういうデータが欲しいのか」をデータベースに直接指示することができます。データベース自身がその場にあるデータを検索し、絞り込んだ結果だけを返すため、高速に探索できるのです。


## "テーブル"という概念

tableとは「表」という意味ですね。見た目通り、こういう表のことです。

| id | name | gender | birthday |
|:-:|:-:|:-:|:-:|
|1| 佐藤陽子 | 女性 | 1990-01-01 |
|2| 鈴木花子 | 女性 | 1995-12-02 |
|3| 田中次郎 | 男性 | 2000-10-25 |
|...| ... | ... | ...|

SQLの世界では、どんな複雑なデータであろうと、必ずテーブルの形にして保存されます。
↑のようなユーザー情報もそうですし、アクセスログのような情報もテーブルの形式に作れますよね。

| time | status | path | remote_ip |
|:-:|:-:|:-:|:-:|
| 2017-01-01 01:00:01  | 200  | /login  | 192.0.2.1  |
| 2017-01-01 01:00:02  | 200  | /item/123  |  192.0.2.2 |
| 2017-01-01 01:00:03  | 403  | /mypage/123  |  192.0.2.3 |
| ... | ... | ... | ... |

## テーブルについてもう少し

* 行と列があります。
    * 1列1列をカラム、フィールドなどと呼ぶこともあります。
    * 1行1行をロウ、レコードなどと呼ぶこともあります。
        * 結構あやふやです。
* それぞれの枠には、**スカラ(scalar)**と呼ばれる単純な数字や文字列が入っています
    * 詳しくは次回書きます。
* 表は入れ子にできません。
    * 表の1カラムに入っているのは、必ずスカラです。別の表をそのまま保存することはできません。
    * 複雑なデータは、テーブルを分割することで表現します。

「テーブルを分割すると複雑なデータも表現できる」ですが、例えば以下のようなイメージです。

> SNSのデータを考えてみます。Twitterでもマストドンでもよいです。
SNSにはユーザーが登録し、何か投稿を複数回行います。

ユーザーがそれぞれ複数の投稿をしているのだから、、こんな風にイメージする人がいるかもしれません。

<table>
<tr><th>ユーザー名</th><th>投稿一覧</th></tr>
<tr><td>taro</td><td>
<table>
<tr><th>タイトル</th><th>内容</th></tr>
<tr><td>4/1の日記</td><td>...</td></tr>
<tr><td>4/2の日記</td><td>...</td></tr>
<tr><td>...</td><td>...</td></tr>
</table></td></tr>
<tr><td>hanako</td><td>
<table>
<tr><th>タイトル</th><th>内容</th></tr>
<tr><td>4/1の日記</td><td>...</td></tr>
<tr><td>4/2の日記</td><td>...</td></tr>
<tr><td>...</td><td>...</td></tr>
</table></td></tr>
<tr><td>jiro</td><td>
<table>
<tr><th>タイトル</th><th>内容</th></tr>
<tr><td>4/1の日記</td><td>...</td></tr>
<tr><td>4/2の日記</td><td>...</td></tr>
<tr><td>...</td><td>...</td></tr>
</table></td></tr>
</table>

しかしRDBではこのような構造は許されません。枠の中に入れられるのは単純な文字列や数字だけです。そこで、テーブルを分割し、ユーザー情報と投稿を別々に保存します。

ユーザー名はたぶん変更されることがあるので、変更されないidを適当に発番しておき、投稿にもそのユーザーのidを保存しておきます。

| ユーザーid | ユーザー名 |
|:-:|:-:|
|  1 | taro  |
|  2 | hanako  |
|  3 | jiro  |

| 投稿id | ユーザーid | タイトル | 本文 |
|:-:|:-:|:-:|:-:|
| 1  | 1  | 4/1の日記  | ...  |
| 2  | 1  | 4/2の日記  | ...  |
| 3  | 2  | 5/5の日記  | ...  |
| 4  | 3  | 1/9の日記  | ...  |
| ...  | ...  | ...  | ...  |

投稿だけが固まって保存されていますが、それぞれを投稿したユーザーがわかります。なので、実質同じデータを表現できています。

このように似たような情報をまとめた概念として保存することで、分析しやすくなるなどのメリットもあります。

* 「4/1にSNS全体でいくつ投稿があったのか？」を数えられる
* 「ユーザーごとにいくつ投稿しているのか？」を数えられる
* 「投稿数の多いユーザーは誰？」を調べられる

などなど。DBがこのような構造になっていれば、SELECT文で一瞬で調べることができます。

RDBで検索しやすい・保存できるようなテーブル構造を考えることを正規化と言います。この講座はSELECT文を対象としているので説明しませんが、テーブルの中が単純なデータに限られているのはこんな理由によるものです。

----

この記事は「SQL SELECT基礎」の第1回目です。
[SQL SELECT基礎 目次](http://qiita.com/Hiraku/items/67cf329f1ddb897b1436)
→次の記事は[SQL SELECT基礎(2) スカラ値いろいろ](http://qiita.com/Hiraku/items/2bf26e8cdf117a7f81e8)