首页 > 解决方案 > Laravel 6,MYSQL - 如何使用 Laravel Querybuilder 或 Model Eloquent 将子查询与 GroupBY 左连接?

问题描述

我尝试使用 Laravel Eloquent 来解决这个问题,但我无法获得准确的查询。所以我做了一个原始查询来获取我想要的数据。任何人都可以帮助我如何将其转换为 laravel eloquent 或 Query builder?

SELECT users.*,
       chat.*
FROM users
LEFT JOIN
  (SELECT a.customer_id,
          a.time,
          b.content
   FROM
     (SELECT customer_id,
             MAX(datetimestamp) TIME
      FROM chat_messages
      GROUP BY customer_id) a
   JOIN chat_messages b ON a.customer_id = b.customer_id
   AND a.time = b.datetimestamp) chat ON users.id = chat.customer_id
WHERE users.customer_role != 0
ORDER BY TIME DESC

标签: phpmysqllaraveleloquentgreatest-n-per-group

解决方案


我认为您正在尝试为每个用户获取最新的聊天消息,可以使用左连接重写您的查询以选择每个组的最新记录,并且以 laravel 的查询构建器格式转换此类查询会更容易

SQL

select u.*,c.*
from users u
join chat_messages c on u.id = c.customer_id
left join chat_messages c1 on c.customer_id = c1.customer_id and c.datetimestamp < c1.datetimestamp
where c1.customer_id is null
    and u.customer_role != 0
order by c.datetimestamp desc

查询生成器

DB::table('users as u')
  ->select('u.*, c.*')
  ->join('chat_messages as c', 'u.id', '=', 'c.customer_id' )
  ->leftJoin('chat_messages as c1', function ($join) {
        $join->on('c.customer_id', '=', 'c1.customer_id')
             ->whereRaw(DB::raw('c.datetimestamp < c1.datetimestamp'));
   })
  ->whereNull('c1.customer_id')
  ->where('u.customer_role','!=',0)
  ->orderBy('c.datetimestamp', 'desc')
  ->get();

参考:Laravel Eloquent 选择 max created_at 的所有行


推荐阅读