【问题标题】:Get most recent row with group by and Laravel使用 group by 和 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);

【问题讨论】:

    标签: mysql sql laravel eloquent greatest-n-per-group


    【解决方案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);
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-01-07
            • 1970-01-01
            • 1970-01-01
            • 2012-01-14
            • 2020-12-19
            • 2020-06-24
            • 2016-04-27
            • 1970-01-01
            相关资源
            最近更新 更多