💽
【laravel】順位・ランキングを求める【mysql8系】
Laravelでクエリを叩き、「順位」を集計したい時の自分のやり方を共有したいと思います。
結論、mysql8系から追加されたウィンドウ関数であるrank()を使う方法がおすすめだと思います。
mamp環境だと、確かmysqlが5系だったので、動かないと思います。
シチュエーション
ポストの投稿に対して、複数のコメントがされている。
今回、ポストに対するコメント数のランキングを集計するapiが必要になったとする。
バックエンドはlaravelを使っている。
1位、1位の次は3位とする。
※1位、1位の次を2位としたい場合、DENSE_RANK()を使う。
クエリ
SELECT
posts.id,
COUNT(*),
RANK() OVER(
ORDER by COUNT(*) DESC)
FROM
posts,
comments
WHERE
posts.id = comments.post_id
GROUP BY
posts.id
結果
Laravelに落とし込む
$rankCollection = DB::table('posts')
->select('posts.id',DB::raw('COUNT(*) as comment_sum, RANK() OVER(ORDER BY COUNT(*) DESC) as comment_sum_rank'))
->join('comments', 'posts.id', 'comments.post_id')
->groupBy('posts.id')
->get();
感想
rankを使わなくてもorderbyを使って、コレクションをループさせて、分岐の処理等を加えれば、「1位、1位の次は3位」の要件は満たせますが、
できる限りSQLを使って順位情報を取得できた方が、順位を求めるアルゴリズム、今回の例だとlaravelのコレクションを操作する必要がないので、楽かなと思いました。
Discussion