---
layout: "@/layouts/MarkdownLayout.astro"
---
export const title = "テーブルを分ける、繋げる";
import DockerLink from "@/components/DockerLink.astro";
import OuterLink from "@/components/OuterLink.astro";
# {title}
## テーブルを分ける
例えば、なにか観た映画の率直な感想をデータベースで管理したいとします。
テーブル名: **movies**
| 作品名 | ラベル |
| :----- | :---- |
| インセプション | おもしろい、感動的 |
| マトリックス | おもしろい、難しい |
| 君の名は。 | 感動的、絵がきれい |
| 天空の城ラピュタ | 感動的、面白い |
このテーブルには、いくつかの問題点があります。
1つずつ見ていきましょう。
さてこの中で、面白いと評価された映画を抽出したいとします。
```sql
SELECT * FROM movies WHERE label LIKE '%面白い%';
```
<br />
結果
| 作品名 | ラベル |
| :----- | :---- |
| 天空の城ラピュタ | 感動的、面白い |
`インセプション`と`マトリックス`が抽出されません。それもそのはず、`おもしろい`と`面白い`は別の文字列だからです。
では、SQLの条件に`OR`で繋げればいいのでしょうか?
```sql
SELECT * FROM movies WHERE label LIKE '%おもしろい%' OR label LIKE '%面白い%';
```
<br />
| 作品名 | ラベル |
| :----- | :---- |
| インセプション | おもしろい、感動的 |
| マトリックス | おもしろい、難しい |
| 天空の城ラピュタ | 感動的、面白い |
確かに見た目上は、すべて抽出できました。
しかし、この面白いという評価は、他にも`おもろい`など、様々な表現があるかもしれません。
いま登場した`おもしろい`、`面白い`、`おもろい`などのように、同じ意味を持つが異なる表現を**同義語**と呼びます。
これをすべてSQLの条件に`OR`で繋げていくのは、あまりにも非効率です。
このような問題を解決するために、テーブルを分けて管理する方法があります。
以下のようなテーブルを用意してみました。
テーブル名: **movie_labels**
| ID | ラベル |
| --: | :---- |
| 1 | おもしろい |
| 2 | 感動的 |
| 3 | 難しい |
| 4 | 絵がきれい |
| ~ | \~中略\~ |
| 10 | 自分の好み |
`movies`テーブルのラベル列を、この`movie_labels`テーブルのIDを使うようにしてみます。
| 作品名 | ラベルID |
| :----- | :---- |
| インセプション | 1,2 |
| マトリックス | 1,3 |
| 君の名は。 | 2,4 |
| 天空の城ラピュタ | 2,1 |
これで、おもしろいと評価する映画を抽出するSQLは、以下のようになります。
```sql
SELECT * FROM movies WHERE label_id LIKE '%1%';
```
<br />
| 作品名 | ラベルID |
| :----- | :---- |
| インセプション | 1,2 |
| マトリックス | 1,3 |
| 天空の城ラピュタ | 2,1 |