我有一个Laravel应用程序,我有一个应该按如下方式运行的查询。
company date period
apple | 2017-08-23 | live
apple | 2017-09-04 | live
apple | 2014-03-04 | history
enron | 1987-09-09 | history
tesla | 2017-07-04 | live
tesla | 2017-06-03 | live
它需要按日期降序对每个公司的条目进行排序,条件为period ='live',从而返回每个公司的最后一个“实时”条目。在上面的例子中,这应该返回
company date
apple | 2017-09-04
tesla | 2017-07-04
我试图使用查询构建器完成此操作,如下所示:
return $query->where('period', '=', 'live')
->groupBy('company')
->orderBy('date','desc');
然而,这首先对结果进行分组,然后对它们进行排序,这会产生不可预测的结果。根据这个问题/答案,答案在于子查询:
ORDER BY date and time BEFORE GROUP BY name in mysql
但是,我无法将这种方法纳入我的问题。您是否可以向我解释如何有效地解决此问题,无论是使用子查询还是使用不同的方法,而不是诉诸原始查询?
答案 0 :(得分:1)
您当前所需输出的策略是正确的,并且您不需要子查询。以下原始MySQL查询应该足够了:
SELECT company, MAX(date)
FROM companies
GROUP BY company
我们可以尝试以下Laravel代码:
return $query->where('period', '=', 'live')
->groupBy('company')
->orderBy('date','desc')
->get(['company', DB::raw('MAX(date) AS max_date')]);
与您在问题中所说的相反,如果您使用ORDER BY
查询并且表中的基础数据没有更改,那么查询结果应该是完全可重现的。
修改强>
与您的问题相反,您的评论表明您希望每个公司的每个最大日期都有匹配的整行。如果是这样,那么你真的想要以下原始MySQL查询:
SELECT c1.*
FROM companies c1
INNER JOIN
(
SELECT company, MAX(date) AS max_date
FROM companies
GROUP BY company
) c2
ON c1.company = c2.company AND
c1.date = c2.max_date
我们可以尝试编写以下Laravel代码来处理这个问题:
DB::table('companies')
->select('*')
->join(DB::raw('(SELECT company, MAX(date) AS max_date
FROM companies GROUP BY company) c2'), function($join)
{
$join->on('companies.company', '=', 'c2.company');
$join->on('companies.date', '=', 'c2.max_date');
})
->orderBy('companies.date', 'DESC')
->get();
答案 1 :(得分:1)
另一个解决方案可能是简单groupBy()
已排序的查询结果(https://laravel.com/docs/5.5/collections#method-groupby)
它完全取决于结果数据集的大小
答案 2 :(得分:0)
https://laravel.com/docs/5.5/queries#retrieving-results看看这个链接。你应该使用DB :: table('company') - > where('period','live') - > groupBy('your condition') - > orderBy('your condition') - > get( ); 它将返回StdClass对象。如果你想要一个数组在get()之后添加toArray(); 希望它有效,让我知道。