使用group by和Laravel获取最近的行

ckx4rj1h  于 2023-01-27  发布在  其他
关注(0)|答案(6)|浏览(255)

即使有多个类似这样的问题,我也无法让查询返回包含最近日期和分组依据的行。
我有下表。

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

uwopmtnx1#

问题是结果集将首先被 * 分组 *,然后被 * 排序 *。您可以使用嵌套选择来获得您想要的结果。
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()子句。

2wnc66cl

2wnc66cl2#

您可以将groupBy替换为distinct,就像在我的例子中一样。

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

希望这个有用。

jdg4fx2g

jdg4fx2g3#

如果有人仍然在寻找一个简短而雄辩的答案,使用groupBy()latest()只需添加unique()get()像这样...

$unreadMessages = Message::where('receiver_id', Auth::user()->id)
    ->where('read_at', null)
    ->latest()
    ->get()
    ->unique('user_id');
  • --更新---
    上述解决方案的问题在于,它对结果集使用unique()方法,这是低效的,因为它是在从数据库检索结果集之后对整个结果集进行操作的。这可能是缓慢的并且是资源密集型的,尤其是在处理大型数据集时。
  • 溶液1

$unreadMessages =消息::其中("接收方ID",验证::用户()-〉ID)-〉其中("读取日期",空)-〉最新("创建日期")-〉分组依据("用户ID")-〉get();
这里,我们在结果集上使用groupBy()方法而不是unique()groupBy()应用于数据库级别,这样效率会高得多。

  • 解决方案二

$unreadMessages =消息::选择('用户标识符',数据库::原始('max(created_at)as max_created_at'),数据库::原始('*'))-〉其中('接收方标识符',身份验证::用户()-〉标识符)-〉其中('read_at ',null)-〉分组依据('用户标识符')-〉get();
在此查询中,我们选择user_idmax(created_at) as max_created_at*,它们将提供所有列。
使用groupBy('user_id')只会选择不同的user_id,而使用max(created_at) as max_created_at则会为您提供每个用户的最新消息,这样,您只需对数据库进行一次查询就可以检索每个用户的最新未读消息。

2g32fytz

2g32fytz4#

要获取每个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选择具有最大创建时间的所有行

zy1mlcev

zy1mlcev5#

在您的示例中有一个日期字段,而不是日期时间字段,因此下面是我的首选方法:

# 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();
  • 注意,上面的操作对于日期时间字段不会像预期的那样工作,因为行将具有不同的时间戳,它可能只返回最新的一行。
wgx48brx

wgx48brx6#

您可能还需要orderBymessage_id

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

相关问题