概要

Laravelで開発していると、

「日付ごとに最新のレコードだけ取得したい」

という場面に必ずぶつかります。

例えば、

  • カレンダーに「その日の最新メモ」だけ表示したい
  • ログを日別にまとめたい
  • ユーザーの最新アクションだけ一覧にしたい

などです。

しかし実際に実装しようとすると、

  • GROUP BY?
  • join?
  • DB::raw?
  • 仮テーブル?

と、急に難しい単語が増えて混乱しがちです。

私自身も最初は

「joinって何してるの?」
「latestってどこから来た?」
「これ本当に合ってる?」

という状態でした。

この記事では、

  • 日付ごとの最新データを取得する仕組みを
  • SQLの知識がほぼ無い状態から
  • 幼稚園児でも分かるレベルまで噛み砕いて

実際のLaravelコードを使いながら解説します。

特に、

  • 仮テーブル(サブクエリ)の考え方
  • join の本当の役割
  • なぜ DB::raw() が必要なのか

この3点を重点的に扱います。

同じところで詰まっている人の
「なるほど!」の助けになれば嬉しいです。

//冒頭
use Illuminate\Support\Facades\DB;
use App\Models\memo;

public function daypage($day_ymd){
//DB::raw()SQLをかけるようにするもの ここから先はSQLで書ける
//SELECT post_day 日時を取り出す
//MAX(created_at) その日の中で一番新しい時間を取る (MAX = いちばん大きい値 = いちばん新しい時間)
//GROUP BY post_day 「日付ごとにまとめる」
//AS latest_time latest_time(仮の名前) って名前をつける

$memos=memo::join(DB::raw('(SELECT post_day, MAX(created_at) AS latest_time FROM memos GROUP BY post_day) latest'),

//仮テーブルの設計書を作成

//memo テーブル
| post_day     | created_at | memo   |
|--------------|------------|--------|
| 2026-10-11  | 10:50      | 投稿1 |
| 2026-10-11  | 11:00      | 投稿2 |
| 2026-10-12  | 10:50      | 投稿3 |
| 2026-10-12  | 11:00      | 投稿4 |

//latest 仮テーブル
| post_day     | latest_time |
|--------------|-------------|
| 2026-10-11  | 11:00       |
| 2026-10-12  | 11:00       |


function ($join) {
//仮テーブル `latest` と 本物テーブル `memos` を  「日付」と「時間」の両方で照合している ↓

$join->on('memos.post_day', '=', 'latest.post_day')

->on('memos.created_at', '=', 'latest.latest_time');

})->get();

//最終$memoにはこれが入る
| post_day     | created_at | memo   |
|--------------|------------|--------|
| 2026-10-11   | 11:00      | 投稿2 |
| 2026-10-12   | 11:00      | 投稿4 |

return view('daypage', compact('day_ymd', 'memos', 'todayMemo'));

}

コードのみ

$memos=memo::join(DB::raw('(SELECT post_day,
MAX(created_at) AS latest_time 
FROM memos GROUP BY post_day) latest'),
            function ($join) {
                $join->on('memos.post_day', '=', 'latest.post_day')
                     ->on('memos.created_at', '=', 'latest.latest_time');
            })
        ->get();