eager_load, preload, includesの違い（自分用まとめ）

- [Rails - INNER JOIN で eager loading - Qiita](http://qiita.com/akishin/items/36dba4b2ccdaefb53dc6)
- [Rails - ActiveRecordのjoinsとpreloadとincludesとeager_loadの違い - Qiita](http://qiita.com/k0kubun/items/80c5a5494f53bb88dc58)
- [ruby on rails - How to write left join on( ~~ and ~~). not left join on ~~ where ~~ in ActiveRecord - Stack Overflow](http://stackoverflow.com/questions/33457833/how-to-write-left-join-on-and-not-left-join-on-where-in-activerec)

発行されているSQLは下記を引用：
[Rails - ActiveRecordのjoinsとpreloadとincludesとeager_loadの違い - Qiita](http://qiita.com/k0kubun/items/80c5a5494f53bb88dc58)

## eager_load
**User.eager_load(:posts)**

```
SELECT `users`.`id` AS t0_r0,
       `users`.`name` AS t0_r1,
       `users`.`created_at` AS t0_r2,
       `users`.`updated_at` AS t0_r3,
       `posts`.`id` AS t1_r0,
       `posts`.`user_id` AS t1_r1,
       `posts`.`created_at` AS t1_r2,
       `posts`.`updated_at` AS t1_r3
FROM `users`
LEFT OUTER JOIN `posts` ON `posts`.`user_id` = `users`.`id`
```


**User.eager_load(:posts).where(posts: { id: 1 })**

```
SELECT `users`.`id` AS t0_r0,
       `users`.`name` AS t0_r1,
       `users`.`created_at` AS t0_r2,
       `users`.`updated_at` AS t0_r3,
       `posts`.`id` AS t1_r0,
       `posts`.`user_id` AS t1_r1,
       `posts`.`created_at` AS t1_r2,
       `posts`.`updated_at` AS t1_r3
FROM `users`
LEFT OUTER JOIN `posts` ON `posts`.`user_id` = `users`.`id`
WHERE `posts`.`id` = 1
```
テーブルを結合して1発でもってくる。
テーブルデータがでかくて結合するのがしんどいやつは`eager_load`ではしんどいと思われる。

さらに重要な点としては結合しているので、`has_many`な関係と結合すると`sum`計算するときに結合してできたぶんのレコードを重複して足し合わせてしまう場合があるかもしれない。

`belongs_to`な関係を取得したい（親を取得したい）場合は`eager_load`にするとSQLの発行回数がpreloadに比べて減らせてうれしいという発想もある。

## preload

**User.preload(:posts)**

```
SELECT `users`.*
FROM `users`

SELECT `posts`.*
FROM `posts`
WHERE `posts`.`user_id` IN (1, 2, 3, ...)
```

**User.preload(:posts).where(posts: { id: 1 })**
preloadをwhereで絞り込むとRoRがダメ（できない）っていう。

```
SELECT `users`.*
FROM `users`
WHERE `posts`.`id` = 1 # => Mysql2::Error: UNKNOWN COLUMN 'posts.id' IN 'where clause': SELECT `users`.* FROM `users` WHERE `posts`.`id` = 1
```

さらに重要な点としては`eager_load`と違ってSQLは2回発行されるが、結合していないので、`sum`計算で結合によって生じた（そもそも結合しないからね）重複分を足し合わせてしまう心配がない。

`has_many`な関係を取得したい（子を取得したい）場合は`preload`にすると`eager_load`だと自分自身が重複してメモリにとられてしまうぶんのメモリを効率的につかえるという発想もある。


## includes
空気を読んで、**eager_load**の挙動か**preload**の挙動に変わる。
**User.includes(:posts).where(posts: { id: 1 })**
と書くと、`preload`は`where`で絞り込めないので、`eager_load`の動きになる（空気読んでる）。


## まとめ
テーブル結合してもメモリとか大丈夫そうだと**eager_load**。でも集計関数などで結合重複ぶんを数えてしまいそうなときは注意。

テーブル結合してメモリとかヤバそうだとSQLの発行回数増えるけど、**preload**。さらに集計関数などで重複ぶんを数えてしまうことがないので（結合しないからそもそも重複しない）扱いやすい。


<br>
追加で**joins**と**merge**も。

ここからはほぼ
[Rails と テーブル結合 - Qiita](http://qiita.com/merrill/items/de6eb7e899753ad3361a)
の該当部分の引用となります。

## joins

**eager_load**, **preload** と違いキャッシュしない。
1回こっきり使用するクエリーの時に使用と思われる。

**joins**は**inner join**を行うので、データは**inner join的に**捨てられる。
つまりデータの**しぼりこみ**に使える。

## merge
joins で結合したテーブルの条件式に、ActiveRecord::Relationを使用することができる。

```
User.joins(:avatar).merge(Avatar.where(id: 1))
=>
SELECT users.* FROM users INNER JOIN avatars ON avatars.resource_id = users.id AND avatars.resource_type = 'User' WHERE avatars.id = 1

# 普通に書いた場合
User.joins(:avatar).where('avatars.id = 1')
or
User.joins(:avatar).where(avatars: {id: 1})
```