使用 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 并选择多字段

使用 MYSQL Group By 获取最受欢迎的值

如何在 Laravel 中禁用 only_full_group_by 选项

如何在 Laravel 中使用具有多态关系的“group by”?

如何在laravel中将Group By与Join表一起使用[重复]