Laravel:如何按ID降序查询每个user_id首次出现的行
解决方案:按id降序取每个user_id的首次出现行
当然可以搞定!不管是用Laravel的Eloquent还是纯SQL,单查询就能实现你的需求——本质上你要的就是每个user_id对应最大id的那一行,按id降序排列后正好就是你要的ID 5、3、2的结果,咱们分两种方式说:
一、用Eloquent实现
你可以通过子查询先获取每个user_id的最大id,再筛选出这些id对应的行,代码示例如下:
如果用DB门面:
$targetRows = DB::table('urls') ->whereIn('id', function ($query) { $query->selectRaw('MAX(id)') ->from('urls') ->groupBy('user_id'); }) ->orderByDesc('id') ->get();
如果有对应的Eloquent模型(比如Url),写法更简洁:
$targetRows = Url::whereIn('id', function ($query) { $query->selectRaw('MAX(id)') ->from('urls') ->groupBy('user_id'); })->orderByDesc('id')->get();
这个逻辑很清晰:子查询先按user_id分组,拿到每个组里最大的id,外层查询再匹配这些id,最后按id降序排列,就得到你要的结果了。
二、纯SQL实现
如果不用Eloquent,纯SQL也有两种靠谱的写法:
方法1:关联子查询(兼容MySQL 5.x及多数数据库)
SELECT u.* FROM urls u INNER JOIN ( SELECT user_id, MAX(id) AS max_id FROM urls GROUP BY user_id ) AS sub_query ON u.id = sub_query.max_id ORDER BY u.id DESC;
方法2:窗口函数(MySQL 8.0+、PostgreSQL等支持)
如果你的数据库支持窗口函数,写法会更直观:
SELECT id, user_id, name FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY id DESC) AS row_num FROM urls ) AS ranked_rows WHERE row_num = 1 ORDER BY id DESC;
这里用PARTITION BY user_id把数据按用户分组,每个组内按id降序排序,给每行标记行号row_num,取行号为1的行就是每个用户的最大id记录,最后再整体按id降序排列。
内容的提问来源于stack exchange,提问作者Jakub Szymsza
相关产品推荐
相关产品推荐

