【Laravel】GROUP BYでグループ化したデータの中から最新レコードを取得する

 こんにちわ、東京は三寒四温ならぬ七寒三温くらいの日々に辟易しているHashiです。今回はLaravelでグループ化したデータの中から各グループの最新レコードのみを取得したいケースに遭遇して、少し手こずったので備忘録も兼ねて紹介したいと思います。

 なお、Laravelとはなんぞやという方は下の記事を参照してください!

環境

 今回の環境は下記の通りとなります。

今回の環境

  • Laravel 5.5
  • MySQL 5.6.37

仕様と要点

 まずは、今回の仕様として下記のようなテーブルがあると仮定します。ちなみに、テーブル名は「status_histories」とします。

ID user_id status
1 1 未申請
2 1 申請中
3 1 承認
4 2 未申請
5 2 申請中
6 3 未申請

 このテーブルには上の表のように「id」,「user_id」,「status」という3つのカラムから構成されているテーブルで、見ての通りユーザーのステータス履歴となっています。

求める結果

 そして、今回このテーブルから欲しい情報は、それぞれのユーザーの最新レーコドということになるので、求める結果は下記の通りとなります。

ID user_id status
3 1 承認
5 2 申請中
6 3 未申請

グループ化したデータから最新レコードを取得する

「GROUP BY」と「ORDER BY」を組み合わせてみる

 さて、各グループの最新レコードは取得していきたいと思いますが、冒頭のとおり少し手こずりました。最初に試したのは下記のコード。


StatusHistory::groupBy('user_id')->orderBy('id','desc')->get();

 見ての通り、「GROUP BY」句と「ORDER BY」句を組み合わせた方法です。グループ化してそれぞれの最新レコードが欲しければ、まず単純にグループ化してソートすればいいと思いますよね。でも、この方法だと期待通りの結果は取得できないんですね。うまくいかない理由は処理の順番にあり、「GROUP BY」と「ORDER BY」の組み合わせの場合は、まず「GROUOP BY」が先に処理されるので、ユーザーIDでグループ化された後にソートされたデータが返ってきてしまうからです。

 つまり、上記の方法だと下表のような結果になるということになります。

ID user_id status
6 3 未申請
4 2 未申請
1 1 未申請

 これでは、全然求めるものと違いますね。

「MAX」を使ってみる

 「GROUP BY」と「ORDER BY」の組み合わせではダメということがわかったので、次に試したのが「MAX」を使う方法です。コードはこちらになります。


StatusHistory::select(DB::raw('MAX(id) As id, user_id, status'))->groupBy('user_id')->get();

 この場合、結果がどうなるかというと下表のようになります。

ID user_id status
3 1 未申請
5 2 未申請
6 3 未申請

 「id」に関しては期待通りのidが返ってきますが、「user_id」と「status」に関しては、最新レコードとは違うレコードのものを取得してしまいます。ということでこれもダメですね。

サブクエリを使ってみる

 そして、最後に試したのがサブクエリを使う方法です。上の「MAX」を使う方法だとidに関しては期待通りの結果が得られるので、上記の方法をサブクエリとして使用してみます。今回は下記のように「whereIn」と組み合わせてみました。


StatusHistory::whereIn('id', function($query) {
   $query->select(DB::raw('MAX(id) As id'))->from('status_histories')->groupBy('user_id');
})->get();

 サブクエリで取得したid(各グループの最新レコード)を、whereInを使って取得しています。これでようやく期待通りの結果が得られました。めでたし、めでたし。しかし、もっとスマートな方法はないものか。。

まとめ

 ということで、今回はLaravelでグループ化したデータの中から各グループの最新レコードを取得する方法を紹介しました。もっとスマート方法がありましたら教えてください。

 それでは、今回はここまで!Hashiでした。また!

この記事のまとめ

  • Laravelでグループ化したデータの中から各グループの最新レコードを取得する方法

お仕事のご相談・ご依頼
お気軽にお問い合わせください!

お仕事の依頼はこちら

著者プロフィール

Taka

東京、奄美大島を拠点にサーフィンとスノーボードが好きなフリーランスのWebクリエイターです。普段はプログラム書いたりデザインしたり映像作ったりしています。いろいろな人の話しを聞くのが好きなので、このブログを通して多くの人と繋がりが出来たら嬉しいです。noteとInstagramもやっているのでフォローしてくれたらありがたいです!

人気記事

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です