【笔记】Laravel groupBy 和 orderBy 同时使用,分组获取最新记录

Laravel tytrock ⋅ 于 2019-05-03 14:07:45 ⋅ 3014 阅读

项目中有这样的需求,需要取出相同项目name的最新一个step

表tasks

idnamestepcreated_at
1项目 112019-05-03 10:00:00
2项目 212019-05-03 10:00:01
3项目 312019-05-03 10:00:02
4项目 122019-05-03 10:00:03

如果使用Laravel查询语句:

Task::groupBy('name')->orderBy('created_at','DESC')->get();

但查询结果不是理想中的结果,返回项目1的step是1,不是2。


所以这种情况,需要用到子查询,SQL原生的语句应该这样写:

select * from (select * from tasks order by created_at desc) as a group by name;

Laravel Eloquent 子查询语法

$sql = Task::orderBy('created_at','DESC');
$lists = Task::select('*')->from(DB::raw('('.$sql->toSql().') as a'))->mergeBindings($sql->getQuery())->groupBy(['name'])->get();

如果结果也需要按照时间进行降序排序的话:

$lists = Task::select('*')->from(DB::raw('('.$sql->toSql().') as a'))->mergeBindings($sql->getQuery())->groupBy(['name'])->orderBy('created_at','DESC')->get();


在高版本的mysql(mysql5.7或以上)里,如果出现子查询无效的情况,得在子查询里加上take

$sql = Task::orderBy('created_at','DESC')->take(10);

解析式这样的:通过 explain 查看执行计划,可以看到没有 limit 的时候,少了一个 DERIVED 操作。DERIVED用于派生表的SELECT(FROM子句的子查询),所以没有它就相当于子句里的排序并没有被执行。


参考:

https://learnku.com/articles/20626

https://jingyan.baidu.com/article/4ae03de3df93cc3eff9e6b37.html

本帖已被设为精华帖!
回复数量: 0
    暂无评论~~
    • 请注意单词拼写,以及中英文排版,参考此页
    • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
    • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
    • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
    • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
    Ctrl+Enter