Laravelのサブクエリでwhere inを設定する方法|SQLの副問合せにはクロージャを使え

Laravel database sql

Laravelのサブクエリでwhere inで絞り込む方法を教えますね。

生のSQLでいえば WHERE col in ( SELECT col FROM b_table where in (a, b, c) )

こういうのをLaravelのEloquentで記述します。
※Facadeでも基本は同じです。

Laravelのサブクエリでwhere inを設定する方法

まずwhereInメソッドを使います。

postsテーブルとtagsテーブルが多対多でリレーションしている場合。

$post->tags、$tag->postsみたいな。

Posts::whereIn('id', function($query){
  $query->select('post_id')
  ->from('post_tags')
  ->where('tag_id', 42);
})->get();

いつもどおりにwhereIn()を使います。

コツは第2引数にクロージャを渡すこと。クロージャは引数を取ります。

大切なのはクロージャの中のselect句で取得するカラムをwhereIn()のidに渡しているカラムとリレーションしているカラムにすること。

ここいでうとposts.idでwhere inしたいので、 post_tagsテーブルから取得するのはposts_tags.post_idということです。

生成されるSQLはこんな感じ。

SELECT * FROM posts WHERE id IN ( SELECT post_id FROM post_tags WHERE tag_id = 42 ) 

 

あと僕はあまり使わないのですがこういう書き方もできるらしい。クロージャを使わないパターンです。

Posts::whereIn('id', PostTag::select('post_id')
  ->where('tag_id', 42)
})->get();

こっちのほうが見た目がシンプルですね。僕もこれからこっちにしようかな。

昔のLaravel5とかのときにはこの書き方はできなかった気がします。

新しいバージョンを使っている人はこちらのほうが可読性も高いので推奨します!

 

 

Laravel公式はこちら。

https://laravel.com/api/9.x/Illuminate/Database/Query/Builder.html#method_whereIn