Laravel仅加入了最新行

时间:2019-03-12 15:43:22

标签: php mysql laravel

我正在寻找一种方法(最好使用Laravel的查询生成器)仅联接两个具有一对多关系的表上的“最新行”。

这是我的意思的简化示例:

Table 1 - robots
robotID
name

Table 2 - locations
locationID
robotID
latitude
longitude
date (Y-m-d)

我想要一个robots列表,其中仅包含locations的最新行(按locations.date排序)。 我发现这听起来很简单(因此答案可能很明显!),但是如果不使用for循环,这是非常慢的,我将无法轻易获得预期的结果。

期望的结果最好是每个robot及其最近的location。我已经尝试了以下方法,但是没有达到预期的效果。我可能会过得很慢。

Robot::whereIn('robots.robotID', [1,2,3,4])
->leftJoin('locations', function ($join) {
    $join->on('locations.robotID', '=', 'robots.robotID');
})
->orderBy('locations.date', 'desc')
->groupBy('robots.robotID')
->get();

谢谢!

1 个答案:

答案 0 :(得分:2)

groupBy并不是要那样使用。分组依据是指为了聚合的目的而创建数据组。如果按列分组,则所有其他未聚合列的列值是任意的,不一定与其他列匹配,这很不好。您需要大量修改逻辑才能实现所需的功能,或者可以使用Eloquent relationships来获取具有最新相关位置的机器人作为关系条目。

我将建议后者,因为它在OOP代码中看起来要好得多(不一定是因为它更好或更快速)。

诚然,此解决方案有点笨拙,并且有一个主要缺点。该查询仍会在后台获取所有模型,但每个机器人只会匹配一个模型。

在模型中定义您的关系:

class Robot extends Model {
  ...
  public function latestLocation() { 
       $this->hasOne(Location::class, 'robotID', 'locationID')->latest();
  }
}


$robots = Robot::whereIn('robots.robotID', [1,2,3,4])
->with('latestLocation')
->get();

然后您可以通过以下方式访问位置:

 $robots->first()->latestLocation;