LoginSignup
3
3

More than 5 years have passed since last update.

Laravelにおけるdistinctありのページネーションでの総件数の求め方

Last updated at Posted at 2018-03-28

Laravelのページネーションでdistinctを使うと総ヒット件数が正しく計算されない。
自分はLaravel 5.2で経験したが、最新のバージョンだと修正されているかもしれない(が調べたところ5.4ではおかしいらしい)(いや、修正されたのか??)。

https://stackoverflow.com/questions/41283083/distinct-with-pagination-in-laravel-5-2-not-working
https://github.com/laravel/framework/issues/21242

distinctを使わなければいいのだが、そうはいかない場合もある。
そこで対応したのが以下の方法(5.2を想定)。
例だとdistinctを使う意味がないと思うがそこは複雑なSQLを脳内補完してほしい。

DB::enableQueryLog();

$page    = 2;
$limit   = 20;
$builder = User::select('id', 'name')->distinct()->orderBy('id', 'desc');
$users   = $builder->skip(($page - 1) * $limit)->take($limit)->get();

// totalの計算
$queries     = DB::getQueryLog();
$last_query  = end($queries);
$total_query = preg_replace('/\sorder\sby.+?$/', '', $last_query['query']);
$total       = DB::select(DB::raw('select count(*) as total from (' . $total_query . ') tmp_users'), $last_query['bindings']);

DB::disableQueryLog();

クエリーログを有効化して、最後に実行したSQLを取得する。
$last_query['query']にそのSQLが格納されているのだが、そこには

select distinct `id`, `name` from `users` order by `id` desc limit 20 offset 20

が入っていて、これだと総件数は求められない。
そこで正規表現でorder by以下を削除する。

select distinct `id`, `name` from `users`

これをselect count(*)することでdistinctでも正しい総件数が得られるようになる。
以上:pray_tone2:

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3