勉強会での小話1

# はじめに

この記事は2023年度の振り返りです。

こちらの続きとなります。

https://qiita.com/youfuku/items/ad1cfd0712709eaabdc1

問題を解いてる時の実話を元に、（実験で）対話形式で書いてみました

# 問題
こんなテーブルがあったとする
(テーブル構成に突っ込みどころは多数あると思いますが、割愛して見逃してください)

```sh:作者テーブル
irb(main):003> Author.all
  Author Load (0.4ms)  SELECT `authors`.* FROM `authors`
+----+-----------+-------------------------+-------------------------+
| id | name      | created_at              | updated_at              |
+----+-----------+-------------------------+-------------------------+
| 1  | 岸本 斉史 | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 2  | 村田 雄介 | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 3  | 冨樫 義博 | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 4  | 鳥山 明   | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
+----+-----------+-------------------------+-------------------------+
```

```sh:作成者テーブル
irb(main):005> Write.all
  Write Load (0.5ms)  SELECT `writes`.* FROM `writes`
+----+---------+---------+-------------------------+-------------------------+
| id | book_id | user_id | created_at              | updated_at              |
+----+---------+---------+-------------------------+-------------------------+
| 1  | 1       | 1       | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 2  | 2       | 1       | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 3  | 3       | 2       | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 4  | 4       | 2       | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 5  | 5       | 3       | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 6  | 6       | 3       | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 7  | 7       | 4       | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 8  | 8       | 4       | 2023-12-22 14:32:30 UTC | 2023-12-22 14:32:30 UTC |
+----+---------+---------+-------------------------+-------------------------+
```

```sh:漫画テーブル
irb(main):004> Comic.all
  Comic Load (0.5ms)  SELECT `comics`.* FROM `comics`
+----+------------------+-------------------------+-------------------------+
| id | name             | created_at              | updated_at              |
+----+------------------+-------------------------+-------------------------+
| 1  | NARUTO -ナルト-  | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 2  | BORUTO -ボルト-  | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 3  | アイシールド21   | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 4  | ワンパンマン     | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 5  | 幽☆遊☆白書     | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 6  | HUNTER×HUNTER   | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 7  | Dr.スランプ      | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
| 8  | ドラゴンボール   | 2023-12-22 14:32:29 UTC | 2023-12-22 14:32:29 UTC |
+----+------------------+-------------------------+-------------------------+
```

```sh:問題
Author(作者テーブル)で、「冨樫 義博」が書いている漫画を取得するSQLをactive recordで作成してください
```

# 勉強会内の小話

初学者達：たぶんこんな感じじゃないですか？

```ruby
author = Author.find_by(name: '冨樫 義博')
write_ids = Write.where(user_id: author.id).pluck(:book_id)
p Comic.where(id: write_ids)
```

講師：戻ってくる解答としては正しいけど、これ3回クエリ走るんじゃない？
```sql
SELECT `authors`.* FROM `authors` WHERE `authors`.`name` = '冨樫 義博' LIMIT 1
SELECT `writes`.`book_id` FROM `writes` WHERE `writes`.`user_id` = 3
SELECT `comics`.* FROM `comics` WHERE `comics`.`id` IN (5, 6)
```

初学者達：ですね

講師：解き方は色々あるだろうけど、まずはサブクエリを使ってクエリ減らせるよ？

初学者達：サブクエリってなんですか？

講師：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632357/04ecf476-4747-4472-2f97-9805185d063d.png)

講師：よ、よし。まずはここで勉強しよう

https://qiita.com/aki3061/items/6df0513ccc5aa40a075a

初学者達：でも、これってSQLの話であって、active recordじゃ作れませんよね


講師：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3632357/04ecf476-4747-4472-2f97-9805185d063d.png)

講師：普通にできる・・・よ？

講師：さっき解答したやつを少し変えるだけ

```ruby
author = Author.where(name: '冨樫 義博')
write = Write.where(user_id: author).select(:book_id)
p Comic.where(id: write)
```
```sql
SELECT `comics`.* 
FROM `comics` 
WHERE `comics`.`id` IN (
    SELECT `writes`.`book_id` 
    FROM `writes` 
    WHERE `writes`.`user_id` IN (
        SELECT `authors`.`id` 
        FROM `authors` 
        WHERE `authors`.`name` = '冨樫 義博'
    )
)
```

初学者達：おーー。クエリが一つになった！

初学者達：でも、なんでこっちにはselect書いてるんですか？

```ruby
author = Author.where(name: '冨樫 義博')
write = Write.where(user_id: author).select(:book_id)　# ←ココ
p Comic.where(id: write)
```

講師：書かない場合、デフォルトでIDが利用される。試しにやってみよう

```ruby
author = Author.where(name: '冨樫 義博')
write = Write.where(user_id: author)
p Comic.where(id: write)
```
```sql
SELECT `comics`.* 
FROM `comics` 
WHERE `comics`.`id` IN (
    SELECT `writes`.`id`  -- ← ココが変わってる
    FROM `writes` 
    WHERE `writes`.`user_id` IN (
        SELECT `authors`.`id` 
        FROM `authors` 
        WHERE `authors`.`name` = '冨樫 義博'
    )
)
```

講師：結果、意味の異なる検索結果になるんで、この場合は必要ですね。まぁ、明示的にきちんとselect(:id)と書いてやってた方が、メンバーに優しいとは思うよ。

初学者達：なるほど！

# さいごに
初の対話形式の記事を書いてみました。
少し短いですが、今回はここまでとします。
この勉強会の話は色々あるので、可能な範囲短く区切ってシリーズにしてみようと思います。