使用 group by 和 Laravel 获取最新行
Posted
技术标签:
【中文标题】使用 group by 和 Laravel 获取最新行【英文标题】:Get most recent row with group by and Laravel 【发布时间】:2017-09-03 01:50:29 【问题描述】:即使有多个像这样的问题,我也无法让我的查询返回具有最近日期的行和分组依据。
我有下表..
| message_id | from | to | created_at | status
----------------------------------------------
| 1 | 1 | 2 | 2017-04-06 | 1
| 2 | 1 | 2 | 2017-04-07 | 0
| 3 | 3 | 4 | 2017-04-06 | 1
| 4 | 3 | 4 | 2017-04-07 | 0
----------------------------------------------
我正在尝试获取最近日期的行。
| message_id | from | to | created_at | status
----------------------------------------------
| 2 | 1 | 2 | 2017-04-07 | 0
| 4 | 3 | 4 | 2017-04-07 | 0
当前此查询返回最近日期的行。
$messages = Message::where('to', Auth::id())
->groupBy('from')
->orderBy('created_at', 'DESC')
->paginate(10);
【问题讨论】:
【参考方案1】:如果有人仍在寻找使用groupBy()
和latest()
的简短而雄辩的答案,只需像这样在get()
之后添加unique()
...
$unreadMessages = Message::where('receiver_id', Auth::user()->id)
->where('read_at', null)
->latest()
->get()
->unique('user_id');
【讨论】:
【参考方案2】:要获取每个 from
的最新记录,您可以使用自联接
DB::table('message as m')
->select('m.*')
->leftJoin('message as m1', function ($join)
$join->on('m.from', '=', 'm1.from')
->whereRaw(DB::raw('m.created_at < m1.created_at'));
)
->whereNull('m1.from')
->orderBy('m.created_at', 'DESC')
->paginate(10);
在 SQL 中它看起来像
select m.*
from message m
left join message m1 on m.from = m1.from
and m.created_at < m1.created_at
where m1.from is null
order by m.created_at desc
Laravel Eloquent select all rows with max created_at
【讨论】:
这是我类似问题的最佳答案。 查询看起来很棒。但是当我尝试在 leftJoin 语句上方添加 where 条件时。它没有给我任何结果。有什么帮助吗? @ManeeshRao 您能否提出一个新问题并详细说明您的问题,因为在 cmets 中,如果没有看到原始代码或条件,我无法建议,谢谢【参考方案3】:您的示例中有一个日期字段,而不是日期时间字段,因此以下是我的首选方法:
# mysql
select * from
your_table
where date_field = (select max(date_field) from your_table)
// Laravel
YourModel:::query()->whereRaw('date_field = (select max(date_field) from your_table)')->get();
请注意,对于日期时间字段,上述内容不会按预期工作,因为行将具有不同的时间戳,它可能只返回单个最新行。
【讨论】:
【参考方案4】:您可以将 groupBy 替换为 distinct,因为它适用于我的情况。
$messages = Message::where('to', Auth::id())
->orderBy('created_at', 'DESC')
->distinct('from')
->paginate(10);
希望这会有所帮助。
【讨论】:
【参考方案5】:问题是结果集将首先分组然后排序。你可以使用嵌套选择来得到你想要的。
SQL 查询:
SELECT t.* FROM (SELECT * FROM messages ORDER BY created_at DESC) t GROUP BY t.from
使用 Laravel:
$messages = Message::select(DB::raw('t.*'))
->from(DB::raw('(SELECT * FROM messages ORDER BY created_at DESC) t'))
->groupBy('t.from')
->get();
您只需要添加您的where()
子句。
【讨论】:
这是在看到类似问题的所有其他答案之后的最佳答案。 @YubarajShrestha,您是否遇到任何错误或您期望的结果不正确? 每次我使用 group by 它都会返回最旧的,我想要的只是最新的。没有错误。 @YubarajShrestha 你能发布你的查询吗?【参考方案6】:您可能还想orderBy
message_id
以及
$messages = Message::where('to', Auth::id())
->groupBy('from')
->orderBy('created_at', 'DESC')
->orderBy('message_id', 'DESC')
->paginate(10);
【讨论】:
以上是关于使用 group by 和 Laravel 获取最新行的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Laravel 8 中使用 PostgreSQL 中的子查询通过 group by 子句获取行值?
Laravel:如何使用 group By 和 sum 并选择多字段
如何在 Laravel 中禁用 only_full_group_by 选项