SQLで覚えるジャニヲタ用語

どうも！ジャニヲタです。
今回は、SQLを使って、ジャニヲタ用語を解説していきたいと思います。
なんでそんなことをしようと思ったのかというと、~~大好きなSnow Manというユニットを宣伝したかったから~~何事も新しいことを勉強するには身近なものに例えると覚えやすいよな〜と思ったからです。
「SQLで覚えるジャニヲタ用語」というタイトルにしましたが、SQLって何？という方もご安心ください。SQLとジャニヲタ用語が一気に身につけられる記事になっています。多分...

## 想定読者
- SQLって何？な方
- Rails初心者（SQLを直接触る機会が少ない方、コンソールに表示されるSQLの意味が分からない方）
- 仕事で使うデータを毎回エンジニアに取得依頼している方
- 彼女や奥さんがジャニヲタなエンジニア
- 非ヲタ・非エンジニア

<img width="308" alt="スクリーンショット 2018-12-10 9.18.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/305538/d08b9196-ba56-f6de-245a-4349249c3a17.png">

## SQLって何？
データベースの定義や操作を行うことができる言語です。
世の中のアプリケーションはデータベースに様々な情報を保存しています。
例えば何かのサイトに登録する時、名前やメールアドレス、住所などを登録しますよね。
それらの情報はデータベースに保存され、管理されています。
「この情報くれよ〜」「この情報保存しておいてよ〜」とデータベースに話しかけるための言語がSQLです。

<img width="959" alt="スクリーンショット 2018-12-06 19.12.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/305538/9f275916-a118-b196-8272-55e054f27e32.png">

Rails学習中の方は、アプリケーションを動かしているときにコンソールを見てみて下さい！
上記の画像では、「SELECT」で始まっている文がSQL文です！
実はSQL文を知らぬ間に実行してくれているんですね〜便利ですね〜◎

## まずは準備をしよう
###  テーブルを用意する
まずは、 **テーブル** を作成します。
テーブルとは、 **データを入れておく箱** のようなものと思って下さい。
データベースは、この箱の集まりです。

今回は、ジャニヲタ用語を説明するにあたって、下記のようなテーブルを用意します。

<img width="620" alt="スクリーンショット 2018-12-09 18.53.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/305538/54a469aa-41e1-8244-92b7-78518ca12bd8.png">

**wotakusテーブル**
ヲタク情報を管理するテーブルです。
ヲタクの名前や、好きなタレント名などを管理します。

**unitsテーブル**
グループ（ジャニーズJr.のユニット）を管理するテーブルです。
デビュー組はグループ、Jr.のグループはユニットと呼ぶことが多い気がするのでユニットとしました。
ユニット名などを管理します。

**talentsテーブル**
ジャニタレ情報を管理するテーブルです。
ジャニタレの氏名や、どのユニットに所属しているかなどを管理します。

テーブルの中に、「id」や「name」などの項目がありますね。これは、 **カラム** といって、箱の中の仕切りを意味します。
idには番号が、nameには名前が...というようにデータを整理します。
EXCELと同じようなイメージです！

<img width="226" alt="スクリーンショット 2018-12-07 10.18.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/305538/712b96d7-c95e-a92b-6ca6-96f144a2571d.png">

下記が実際のSQL文です。
データベースの中にテーブルを作成するためには、「create文」という構文でSQLを書きます。

```sql:create.sql
CREATE TABLE wotakus(id integer, name varchar(100), favorite_talent_id integer, 
 created_at datetime, updated_at datetime);
CREATE TABLE units(id integer, name varchar(100), 
 created_at datetime, updated_at datetime);
CREATE TABLE talents(id integer, name varchar(100), unit_id integer, 
 created_at datetime, updated_at datetime);
```
これでデータを入れておく箱と仕切りができました！
Railsの場合、migrationファイルに「create_table」と書きますが、実はこのようなSQLが生成されています。
Railsさん便利！！

### テーブルにデータを入れる
テーブルを作っただけでは、中身は空っぽです。箱の中にデータを入れてみましょう！
テーブルにデータを投入する為には、「INSERT文」を実行します。

**unitsテーブル**
まずはユニットテーブルにデータを入れます。
今回は「兄組」と呼ばれている3組を入れておきます！

```sql
INSERT INTO units (id, name) VALUES (1, 'Snow Man');
INSERT INTO units (id, name) VALUES (2, 'SixTONES');
INSERT INTO units (id, name) VALUES (3, 'Travis Japan');
```
上記のSQL文を実行すると、下記のようにデータがデータベースに登録されます。
それぞれの行を **レコード** といいます。

| id | name | 
|:-----------------|:------------------|
| 1 | Snow Man |
| 2 | SixTONES |
| 3 | Travis Japan |

３レコード投入されましたね！

**talentsテーブル**
次に、メンバー名を投入していきます。
ジャニーズのタレント全員書くとそれだけでスクロール半端なくなるので、
とりあえず、かつて「BAD BOYS J」というドラマに出演していたSnow Manのメンバー3名をサンプルで入れておきますね。

```sql
INSERT INTO talents (id, name, unit_id) VALUES (1, '岩本照', 1);
INSERT INTO talents (id, name, unit_id) VALUES (2, '深澤辰哉', 1);
INSERT INTO talents (id, name, unit_id) VALUES (3, '渡辺翔太', 1);
```

| id | name | unit_id |
|:-----------------|:------------------|:------------------|
| 1 | 岩本照 | １ |
| 2 | 深澤辰哉 | １ |
| 3 | 渡辺翔太 | １ |

この3人はSnow Manのメンバーなので、unitテーブルの1番（Snow Man）をunit_idに入れておきます。
このように、他のテーブル（今回はunitテーブル）のレコードを参照して下さいね、という意味でもつカラムの値（今回はunit_id）を、 **外部キー** と呼びます。

**wotakusテーブル**

最後に、ヲタク情報を投入しましょう。

```sql
INSERT INTO wotakus (id, name, favorite_talent_id) VALUES (1, 'おがっぴ', 2);
INSERT INTO wotakus (id, name, favorite_talent_id) VALUES (2, 'ヲタ子', 3);
INSERT INTO wotakus (id, name, favorite_talent_id) VALUES (3, 'ジャニ美', 1);
```

おがっぴは私です。僭越ながら、id=1でINSERTさせていただきます。

| id | name | favorite_talent_id |
|:-----------------|:------------------|:------------------|
| 1 | おがっぴ | 2 |
| 2 | ヲタ子 | 3 |
| 3 | ジャニ美 | 10 |

さぁ、準備ができました！
早速SQL文とジャニヲタ用語を一緒に学んでいきましょう！

## ジャニヲタ用語に触れよう
さぁ、SQLを使ってジャニヲタ用語を感じてみよう！

### 担当、自担

> 意味：一番好きなジャニーズタレントのこと。
> 用例：「私は深澤くん担当です！」「私の自担はSnow Manの深澤辰哉くんです！」

今回は私の大好きなユニットSnow Manのダイマを兼ねているので、ガンガンSnow Manメンバーの名前を使っていきたいと思います。
はい、私は「ふっか」こと深澤辰哉くんのことを応援しております。

先ほど実行したCREATE文で、wotakusテーブルに「favorite_talent_id」というカラムを作りました。
「好きなタレントid」...つまり、「自担id」です！
おがっぴの自担idは、wotakusテーブルのおがっぴレコードに入っているので、まずはおがっぴのレコード（id=1）を取得してみましょう！

```sql
SELECT * FROM wotakus WHERE id = 1;
```
これは、

「FROM wotakus」＝wotakusテーブルから
「WHERE id = 1」＝idが1番のレコードの
「SELECT * 」＝全てのカラム（*）を取得する

というSQL文です。このSQL文を実行すると、

| id | name | favorite_talent_id | created_at | updated_at |
|:-----------------|:------------------|:------------------|:------------------|:------------------|
| 1 | おがっぴ | 2 | 2018-12-10 00:00:00 | 2018-12-10 00:00:00 |

このようにデータが取得できます。
おがっぴの自担idは「2」のようですね！
INSERT文では、自担idとtalentsテーブルのidに、対応するデータを入れています。
つまり、下記のようにおがっぴの自担名を辿ることができます。

<img width="292" alt="スクリーンショット_2018-12-09_18_59_28.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/305538/5e63374a-a507-dbce-84a0-0f88862872eb.jpeg">

「SELECT」の後に「*」と指定すると全カラム取得できますが、カラム名を指定して、ピンポイントで取得することもできます。

```sql
SELECT favorite_talent_id FROM wotakus WHERE id = 1;
```

上記のSQLを実行すると、

```
2
```
が返ってきます。

自担idではなく、「深澤辰哉」という名前で取得したい場合は、

```sql
SELECT name FROM talents
WHERE id = 2; -- 一つ前のSQLでゲットした深澤くんのtalent_id
```

こう書いてあげれば、

```
深澤辰哉
```
という文字列が返ってきます。

しかし、
① おがっぴのfavorite_talent_idを取得する
② ①で取得したidをキーにタレント名を取得する
と２段階で自担名を取得するのはちょっとまどろっこしいですね。

一発で「深澤辰哉」という文字列で取得したい場合は、下記のようなSQLでゲットできます。

```sql
SELECT name FROM talents
WHERE id = (
 SELECT favorite_talent_id FROM wotakus
 WHERE id = 1
);
```
急にややこしくなった気がしますね！ちょっと分解していきましょう。
まずは3,4行目だけ見てみましょう。

```sql
-- SELECT name FROM talents
-- WHERE id = (
  SELECT favorite_talent_id FROM wotakus
  WHERE id = 1
-- );
```
先ほど見た、「おがっぴの自担idをゲットする」というSQLです。
深澤くんの2番が返ってきますよね。

次は1,2行目です。
タレントidが？番の人の名前をタレントテーブルから取得するSQLです。

```sql
SELECT name FROM talents
WHERE id = (
--   SELECT favorite_talent_id FROM wotakus
--   WHERE id = 1
);
```

つまり、カッコ内でおがっぴの自担idをゲットして、それをキーにタレント名を取得していた、というだけでした！
これで一気に「深澤辰哉」という文字列がゲットできます！

### 自ユニ
> 意味：自分の応援しているグループ、自担が所属しているグループのこと
> 用例：「私の自ユニはSnow Manです！」

今回は、
「おがっぴが応援しているのは深澤くん。そんな深澤くんが所属しているのはどこのユニット？」
という問いかけへの答えをゲットしていきたいと思います。

```sql
SELECT name FROM units
WHERE id = (
 SELECT unit_id FROM talents 
 LEFT OUTER JOIN wotakus ON wotakus.favorite_talent_id = talents.id 
 WHERE wotakus.id = 1
);
```

は〜〜〜またややこしいSQL...
でも大丈夫。一つ一つ分解していきましょう。

今回欲しいのは、「Snow Man」というユニット名。

| id | name | 
|:-----------------|:------------------|
| 1 | Snow Man |

この「Snow Man」をゲットするためには、
① おがっぴの自担idをゲットする
② ①で取得したタレントが所属しているユニットのidをゲットする
③ ②で取得したidをキーに、ユニット名をゲットする
という3Stepが必要になって来ます。

まずは、3〜5行目を見てみます。

```sql
-- SELECT name FROM units
-- WHERE id = (
  SELECT unit_id FROM wotakus 
  LEFT OUTER JOIN talents ON wotakus.favorite_talent_id = talents.id 
  WHERE wotakus.id = 1
-- );
```
おやおや...見慣れない「LEFT OUTER JOIN」「ON」という単語が出て来ました...
これは、「複数のテーブルをくっつけて、ひとつのテーブルっぽく見せる」という技です。
上記の３行を実行すると、

```
1
```
が取得できます。
ちょっとややこしいので、上記３行のSQL

```sql
SELECT unit_id FROM wotakus 
LEFT OUTER JOIN talents ON wotakus.favorite_talent_id = talents.id 
WHERE wotakus.id = 1
```

の「unit_id」を「*」に変えて

```sql
SELECT * FROM wotakus 
LEFT OUTER JOIN talents ON wotakus.favorite_talent_id = talents.id 
WHERE wotakus.id = 1
```
としてみます。
「*」は、全カラムのデータを取得するよ！という呪文です。
結果は、こうなります。

| wotakus.id | wotakus.name | wotakus.favorite_talent_id | talents.id | talents.name | talents.unit_id |
|:-----------------|:------------------|:------------------|:------------------|:------------------|:------------------|
| 1 | おがっぴ | 2 | 2 | 深澤辰哉 | 1 |

※「wotakus.id」は、「wotakusテーブルのidカラム」を表現しています
※「created_at」「updated_at」は省略しています

つまり、
「ヲタクテーブルの自担カラムと、タレントテーブルのidが同じレコードを合体させるよ！」
（```wotakus.favorite_talent_id = talents.id```）
ということでした。

<img width="833" alt="スクリーンショット_2018-12-09_19_28_42.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/305538/b455162c-122d-a9a3-e8a1-b9bd8f281302.jpeg">


ですので、カッコ内の３行では、unit_id「1」が取得できた、というわけです。

<img width="833" alt="スクリーンショット_2018-12-09_19_28_42.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/305538/0976d94c-1c77-57fe-5ce1-2424d9c90645.jpeg">


あとはお馴染みのSELECT文です！

```sql
SELECT name FROM units
WHERE id = (
--   SELECT unit_id FROM wotakus 
--   LEFT OUTER JOIN talents ON wotakus.favorite_talent_id = talents.id 
--   WHERE wotakus.id = 1
-- ※↑上記３行で1が取れました
);
```
unitのidが１番のname（ユニット名）を取得です。
最終的に「Snow Man」がゲットできました！

### 担降り
> 意味：ファンをやめること。
> 用例：「ちょっと私xxの担当降りるわ」

ジャニタレの熱愛報道が出たら、「はてなブログ　担降り」で検索すると、
悲痛なブログが読めたりします。

| id | name | favorite_talent_id |
|:-----------------|:------------------|:------------------|
| 3 | ジャニ美 | 10 |

タレントid=10が誰かは分かりませんが、ジャニ美ちゃんは担当を降りることを決めたそうな。
この10という値、悲しいけど消しましょう...

```sql
UPDATE wotakus SET favorite_talent_id = NULL WHERE id = 3
```
「UPDATE」は、レコードを更新できる構文です。
今回はジャニ美ちゃんのfavorite_talent_idをNULL（空っぽ）にしました。

必ずしも担当がいるジャニヲタだけではないので、favorite_talent_idはNULL可にしときましょう。

さて、ここがジャニヲタ用語の難しいところなんですが、もう１つ意味があるんですよね。
「私、ずっとxxくんのファンやってたけど、歌声聴いて惚れて **渡辺翔太くんに担降り** した！」
のように、別のジャニタレに乗り換えたときも「担降り」を使うんですね！
つまりこういうことです。

```sql
UPDATE wotakus SET favorite_talent_id = '3' WHERE id = 3
```

ジャニ美ちゃんのfavorite_talent_idを「3」(渡辺翔太くんのタレントid)にUPDATEしました。

### ヲタ卒
> 意味：ジャニヲタをやめること
> 用例：「歳も歳だしそろそろヲタ卒して婚活でもすっか〜」

まず、声を大にして言いたいのは、
「 **いくつになってもジャニヲタでいていいだろ！一生ヲタク上等！** 」
ということです。
この度ヲタ子がヲタ卒をしてしまうそうです。悲しいけどテーブルから削除しましょう。

```sql
DELETE FROM wotakus WHERE id = 2
```
上記を実行したあと、ヲタクテーブルを見てみましょう。

```sql
SELECT * FROM wotakus
```

| id | name | favorite_talent_id |
|:-----------------|:------------------|:------------------|
| 1 | おがっぴ | 2 |
| 3 | ジャニ美 | 10 |

ヲタ子はヲタクテーブルから消滅してしまいました...
私がこのSQL文を流すことは一生なさそうです。

### 同担
> 意味：応援対象が自分と同じ人
> 用例：「自担がドラマに出たら一気に同担増えたわ〜」

自分と同じfavorite_talent_idを設定しているヲタクを取得します。
まずは深澤くんのタレントidをゲットして、そのidをfavorite_talent_idに設定しているヲタクをゲットしましょう。

```sql
SELECT id, name, favorite_talent_id FROM wotakus
WHERE favorite_talent_id = (
 SELECT id FROM talents WHERE name = '深澤辰哉'
);
```

| id | name | favorite_talent_id |
|:-----------------|:------------------|:------------------|
| 1 | おがっぴ | 2 |
| 10 | おまるちゃん | 2 |
| 55 | のりぞう | 2 |

同担が2人いました！
下記の書き方でも取れますね。

```sql
SELECT name FROM wotakus
WHERE favorite_talent_id = (
 SELECT favorite_talent_id FROM wotakus WHERE id = 1
);
```

同担が何人いるのか？を取得することもできます。

```sql
SELECT COUNT(*) FROM wotakus
WHERE favorite_talent_id = (
 SELECT favorite_talent_id FROM wotakus WHERE id = 1
);
```
「COUNT（数えたいカラム名）」で実行すると、何行HITするか数値でゲットできます。


### 同担拒否
> 意味：応援しているタレントが被る人とは絡みたくない
> 用例：（Twitter自己紹介等で）「xx君担です。同担拒否なので悪しからず」

乙女心って複雑ですよね〜。
今までid=2のように、「idが2番のデータをとる！」というSQLを書いてきましたが、「idが2番じゃないデータをとる！」という時はどうしたら良いのでしょう？

```sql
SELECT name FROM wotakus
WHERE favorite_talent_id <> (
 SELECT favorite_talent_id FROM wotakus WHERE id = 1
);
```
「<>」という書き方が出現しました。これは、「〜じゃない」を意味します。
上記の場合、favorite_talent_idが2じゃない人の名前を取得できます。
他にも、「<=」「>=」で〜以上・〜以下が表現できたりします。

ちなみに私は同担大歓迎です！！みんなでふっかを応援しよう！！

### カケモ
> 意味：好きなタレントが複数いること（掛け持ちの略）
> 用例：（Twitter自己紹介等で）「阿部ちゃんとのえるのカケモです、よろしく！」

データベースの世界では、一つのカラム（仕切り）に一つのデータしか持てません。
現状のテーブル定義だと、1人のヲタクに対して1人の担当しか入れられません。
それでは、どうやってカケモを表現すればいいんだ〜！？

<img width="839" alt="スクリーンショット 2018-12-09 19.49.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/305538/9174d8a6-5d4d-cc34-404d-e2d50960efc9.png">


はい。 **tantosテーブル** （担当テーブル）を作成しました！
これで複数の担当を管理することができるようになります！

**ヲタクテーブル**

| id | name |
|:-----------------|:------------------|
| 1 | おがっぴ |
| 3 | ジャニ美 |
| 4 | ミーハー花子 |

**タレントテーブル**

| id | name | unit_id |
|:-----------------|:------------------|:------------------|
| 1 | 岩本照 | 1 |
| 2 | 深澤辰哉 | 1 |
| : | : | : |
| 6 | 阿部亮平 | 1 |
| 7 | 川島如恵留 | 3 |
| : | : | : |


**担当テーブル**

| id | wotaku_id | talent_id |
|:-----------------|:------------------|:------------------|
| 1 | 1 | 2 |
| 2 | 3 | 3 |
| 3 | 4 | 6 |
| 4 | 4 | 7 |
| : | : | : |

ミーハー花子(wotaku_id=4)のレコードが、担当テーブルに２行ありますね。

```sql
SELECT * FROM tantos WHERE wotaku_id = 4
```

| id | wotaku_id | talent_id |
|:-----------------|:------------------|:------------------|
| 3 | 4 | 6 |
| 4 | 4 | 7 |

数字だけだと分かりづらいので、JOINしてみましょうか。

```sql
SELECT tanto.wotaku_id ,talents.id ,talents.name FROM tantos
LEFT OUTER JOIN talents ON talents.id = tantos.talent_id
WHERE tantos.wotaku_id = 4 
```
| tantos.wotaku_id | talents.id | talents.name |
|:-----------------|:------------------|:------------------|
| 4 | 6 | 阿部亮平 |
| 4 | 7 | 川島如恵留 |

ミーハー花子は多分勉強できる人が好き。

### 古株、新規
> 意味：ファン歴が長い、ファン歴が短い
> 用例：「あの人は古株だから詳しいよね〜」「ド新規ですがよろしくお願いします」

「ごく出は永遠の新規」という言葉があります。
「ごくせん」からKAT-TUNファンになった人は、いつまで経っても新規、というパワーワードです。
もう、放送から13年経ってますが...！

担当テーブルには「created_at（レコード作成日）」を持っています。
このカラムを使えば、古株・新規が洗い出せそうです（怖い...！）

```sql
SELECT * FROM wotakus 
WHERE talent_id = 2
ORDER BY created_at ASC
```
「ORDER BY」はソートに使うカラムを指定、「ASC」は昇順指定です。
これで深澤担が古株順に並びます...こわひ...！

ちなみに、

```sql
SELECT * FROM wotakus 
WHERE talent_id = 2
ORDER BY created_at ASC
LIMIT 1
```
のように「LIMIT 数値」をつけてあげると、先頭から何行取得するか指定できます。
上記の場合、一番古株の人が取得できます...！

## まとめ
はい、以上で基礎的なジャニヲタ用語のレクチャーを終わります。
出オチ感の強い記事だったかと思いますが、一応CRUDには触れてみました。
ぜひ皆さん、何か新しいことを勉強するときは、自分の好きなものや身の回りの事柄に例えて覚えてみて下さい！
最後まで読んでくれた方、サンキューサンキューで〜す！