通过分组和Laravel获取最近的行

时间:2017-04-07 15:41:45

标签: mysql sql laravel laravel-5 eloquent

即使存在多个这样的问题,我也无法通过分组返回具有最近日期的行。

我有下表..

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

5 个答案:

答案 0 :(得分:6)

问题是结果集将首先分组然后命令。您可以使用嵌套选择来获得所需内容。

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()条款即可。

答案 1 :(得分:2)

您可以将groupBy替换为distinct,因为它适用于我的情况。

$messages = Message::where('to', Auth::id())
                ->orderBy('created_at', 'DESC')
                ->distinct('from')
                ->paginate(10);

希望这会有所帮助。

答案 2 :(得分:0)

示例中有一个日期字段,而不是datetime字段,因此以下是我的首选方法:

# 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();
  • 请注意,上述操作对于datetime字段将无法正常工作,因为这些行将具有不同的时间戳记,因此很可能只返回单个最新行。

答案 3 :(得分:0)

要获取每个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

答案 4 :(得分:-1)

您可能还想orderBy message_id

$messages = Message::where('to', Auth::id())
                    ->groupBy('from')
                    ->orderBy('created_at', 'DESC')
                    ->orderBy('message_id', 'DESC')
                    ->paginate(10);