我确实有一张桌子,里面有多个访客。在我的结果列表中,只显示每个访问者的最后一次访问。
表格如下:
id | created_at | descr | website | source
------------------------------------------
2 | 2017_12_22 | john | john1.com | a
3 | 2017_12_23 | marc | ssdff.com | b
4 | 2017_12_24 | john | john1.com | c
5 | 2017_12_24 | tina | def.com | b
6 | 2017_12_25 | stef | abc.com | a
7 | 2017_12_26 | john | john2.com | c
如果我做了
->orderBy('visitors.created_at', 'desc')
->groupBy('visitors.descr')
结果列表是正确的,因为每个访问者只显示一次。但我需要最新出现的访问者,结果列表显示第一次出现。因此,我希望看到ID 7而不是ID 2。
以下查询解决了该问题:
select *
from visitors as v
INNER JOIN ( select descr , MAX(created_at) as max_created
from visitors as v
group by descr ) AS M
where v.descr = M.descr AND v.created_at = M.max_created
ORDER BY created_at DESC
有人可以帮助将其变为雄辩或让我进入另一个方向吗?
答案 0 :(得分:0)
为什么不直接像这样直接查询sql:
DB::table('visitors')->select("
select *
from visitors as v
INNER JOIN ( select descr , MAX(created_at) as max_created
from visitors as v
group by descr ) AS M
where v.descr = M.descr AND v.created_at = M.max_created
ORDER BY created_at DESC
");
在eloquent中,查询将是这样的:
DB::table('visitors as v')
->join(DB::raw("( select descr , MAX(created_at) as max_created
from visitors as v
group by descr ) AS M "),'v.id','=','M.id')
->select('*')
->where('v.descr','M.descr')->where('v.created_at','M.max_created')
->orderBy('created_at','desc')
->get()
答案 1 :(得分:0)
如果您可以使用AUTO_INCREMENT id
列而不是created_at
,则可以使用其他方式获得(相同)结果:
select *
from visitors
where id in (
select MAX(id)
from visitors
group by descr
)
ORDER BY id DESC
此查询的效率可能较低,但由于whereIn()
支持子查询,因此更容易使用eloquent。
$subQuery = Visitor::groupBy('descr')->select(DB::raw('max(id)'));
$latestVisitors = Visitor::whereIn('id', $subQuery)->orderBy('id', 'desc')->get();
请注意,如果descr
中的值相同,则原始查询可以按created_at
返回多行。使用id
不会发生这种情况,因为它是唯一的。
答案 2 :(得分:0)
您可以在访客模型中编写帮助关系
public function lastVisit()
{
$this->hasOne('VisitModel')->latest();
}
然后只需访问上次访问的所有访问者
$visitors = Visitor::with('lastVisit')->get();
真的就是这一切。