概要
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();