不使用 orderBy 取 N 个最新记录

Posted

技术标签:

【中文标题】不使用 orderBy 取 N 个最新记录【英文标题】:Take N latest records without using orderBy 【发布时间】:2021-06-10 10:01:38 【问题描述】:

我遇到了一个优化问题,需要从有很多记录的数据库中获取n latest 结果。我知道我可以使用orderBy 来做到这一点,但我想避免它,因为orderBy 循环遍历每条记录,这增加了我的加载和查询时间。我在take() 中找到了一个使用负数的answer,它基本上记录了最新记录,但它对我不起作用,无论如何它都会记录所有记录:

Record::all()->take(-5);

这是之前代码的输出,只返回空的Query Builder实例:

  "supplementRecommendationsHistory" => Illuminate\Database\Eloquent\Builder #2485 ▼
    #query: Illuminate\Database\Query\Builder #2484 ▶
    #model: App\RecommendedSupplement #2483 ▶
    #eagerLoad: array:2 [▶]
    #localMacros: []
    #onDelete: null
    #passthru: array:17 [▶]
    #scopes: []
    #removedScopes: []
  

这有什么不同的方法吗?感谢任何帮助。

【问题讨论】:

只需latest 表示您要订购。如果您有自动增量列,则从表模式中找到下一个 ID 并执行 WHERE id > :nextIndex - N @Justinas 完全正确。将您的表视为一组无序的行。您必须使用orderBy,除非您希望您的结果以不可预知的顺序排列。好消息?当您 orderBy 表中的索引列时,它并不像您想象的那么昂贵。 看这篇关于mysql中group by/limit优化的文章percona.com/blog/2006/09/01/… 谢谢你们的建议。我接受了@Justinas 的建议WHERE id > :nextIndex - N,它现在似乎有效。 @zlatan 你能发布实现作为答案吗?因为显然WHERE id > :nextIndex - N 作为普通查询永远不会起作用 【参考方案1】:

根据 cmets (@Justinas) 的建议,这就是我实施 WHERE id > :nextIndex - N 解决方案的方式:

RecommendedTest::where('id', '>', RecommendedTest::max('id') - 20)->get()->reverse()->values();

这样我可以从一个庞大的数据库中获取最新的 20 条记录。我还使用reverse()->values() 来恢复结果的排序,这基本上给了我按 created_at 列排序的结果,这是我最初的目标。查询时间不长,大约 1000 毫秒,这对我来说没问题,因为这是临时解决方案。

reverse 和 values 方法的文档

【讨论】:

以上是关于不使用 orderBy 取 N 个最新记录的主要内容,如果未能解决你的问题,请参考以下文章

MSSQL分组取后每一组的最新一条记录

如果列有 2 个相同的记录,则选择最新记录

按更新时间取最新记录

top与with ties用法

mysql联合查询

如何在 Laravel 中获取最新的活动记录?