简体   繁体   English

Laravel只加入了最新行

[英]Laravel left join only the most recent row

I'm looking for a way (preferably using Laravel's query builder) to only join the "most recent row" on two tables that have a one-to-many relation. 我正在寻找一种方法(最好使用Laravel的查询生成器)仅联接具有一对多关系的两个表上的“最新行”。

Here's a simplified example of what I mean: 这是我的意思的简化示例:

Table 1 - robots
robotID
name

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

I'd like to have a list of robots with only their most recent row from locations (ordered by locations.date ). 我想列出一个robots列表,其中仅包含locations最新行(按locations.date排序)。 I've found that it sounds very simple (so the answer could be obvious!) but I can't get the expected outcome very easily without using a for-loop, which is very slow. 我发现这听起来很简单(因此答案可能很明显!),但是如果不使用for循环(这非常慢),我将很难轻易获得预期的结果。

The expected outcome is preferably each robot with their most recent location . 预期结果最好是每个robot及其最近的location I've tried the following, but it's not as expected. 我已经尝试了以下方法,但是没有达到预期的效果。 I could just be having a slow day. 我可能过得很慢。

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();

Thanks in advance! 提前致谢!

I think you have to using something like this query for your target: 我认为您必须对目标使用类似以下查询的内容:

SELECT l.*, r.name AS robot_name
FROM location l
JOIN (
  SELECT robotID, MAX(date) AS most_recent
  FROM location
  GROUP BY robotID) AS max
ON l.robotID=max.robotID AND l.date=max.most_recent
JOIN robots r ON r.robotID=l.robotID
WHERE r.robotID IN (1, 2, 3, 4)
ORDER BY l.date DESC

groupBy isn't meant to be used that way. groupBy并不是要那样使用。 Group by is meant to create groups of data for the purposes of aggregation. 分组依据是指为了聚合的目的而创建数据组。 If you group by a column then the column values of all other non-aggregated columns is arbitrary and does not necessarily match the others, which is bad. 如果按列分组,则所有其他未聚合列的列值是任意的,不一定与其他列匹配,这很不好。 You need to heavily revise your logic before you can achieve what you need, or you can use Eloquent relationships to get robots with the most recent related location as a relationship entry. 您需要大量修改逻辑才能实现所需的功能,或者可以使用雄辩的关系来获取具有最新相关位置的机器人作为关系条目。

I will be suggesting the later because it looks a lot better in OOP code (not necessarily because it's better or faster). 我会建议后者,因为它在OOP代码中看起来要好得多(不一定是因为它更好或更快速)。

Admittedly this solution is a bit hacky and has one major drawback. 诚然,这种解决方案有点笨拙,并且有一个主要缺点。 The query still gets all models in the background but will only match one with each robot. 该查询仍会在后台获取所有模型,但每个机器人只会匹配一个模型。

Define your relationship in the model: 在模型中定义您的关系:

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();

Then you can access the location via eg 然后您可以通过例如访问位置

 $robots->first()->latestLocation;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM