【PHP】 group_byで最新のレコードを取得したかった

ユーザーへの通知テーブルで、各ユーザーの最新通知のレコードを取得したかった

order_byでいけると思ったがうまくいかなかった

当初の検索部分はこんな感じ
(CodeIgniter使用)

$this->db
    ->where('deleted_at', NULL)
    ->order_by('noticed_at', 'DESC')
    ->group_by('user_id')
    ->get('notices')
    ->result('array');

発行されたクエリ ↓

SELECT *
FROM `notices`
WHERE `deleted_at` IS NULL
GROUP BY `user_id`
ORDER BY `noticed_at` DESC

CodeIgniterではORDER BYがGROUP BYの後に実行されちゃうからうまくいかない

集約関数 max を使用して解決

->order_by('noticed_at', 'DESC')
->where('noticed_at = (select max(noticed_at) from notices)', NULL, FALSE)
に変更する

こんな感じ

$this->db
    ->where('deleted_at', NULL)
    ->where('noticed_at = (select max(noticed_at) from notices)', NULL, FALSE)
    ->group_by('user_id')
    ->get('notices')
    ->result('array');

発行されたクエリ ↓

SELECT *
FROM `notices`
WHERE `deleted_at` IS NULL
AND noticed_at = (select max(noticed_at) from notices)
GROUP BY `user_id`

ざっくり補足
  • 最新のレコードを指定してるコードは下記の通り
    where('noticed_at = (select max(noticed_at) from notices)', NULL, FALSE)
    集約関数はwhere句で直接使えないので、サブクエリ(=入れ子になったSQL)を使用する
  • 集合関数のmaxメソッドを使用すると、最大値を算出できる
    つまり、(select max(noticed_at) from notices)でnoticed_atの一番大きい値を算出してから、whereで条件指定している