将相同的 table 加入多个列并获取包含用户数据的最新记录

join same table with multiple columns and get the latest record with user data

我有两个 table 名为 usersmessage,我想加入两个 tables并从每个用户与用户名的对话中获取最后一条消息。

我想要两个用户之间按时间戳记的最后一条消息,无论是 from_id 还是 to_id,以及同样,希望与我进行过任何对话的每个用户的最后一条消息。

messages table 具有列 from_id、to_id、messages.

下面是我的代码。

$chats = DB::table('users')
    ->leftJoin('messages', function($query)
    {
        $query->on('users.id', '=', 'messages.to_id')
        ->whereRaw('messages.id IN (select MAX(messages.id) from messages join users on users.id = messages.to_id  group by users.id)');
    })
    ->select('users.id as user_id', 'users.name', DB::raw('CONCAT("https://www.interwebs.co.in/puzzle/attach/", users.avatar) AS image') , 'users.mobile', 'messages.id', 'messages.from_id', 'messages.to_id', 'messages.body as message', 'messages.attachment', 'messages.seen as seen_count', 'messages.created_at')
    ->where('messages.from_id', $request->user_id)
    ->get();

我的消息table是

| from_id  | to_id     | message  | created_at          |
| ---------| --------- | ---------| ------------------  |
| 1        | 2         | abc      | 2022-02-04 10:55:34 |
| 2        | 1         | cdef     | 2022-02-05 10:56:34 |
| 1        | 3         | defg     | 2022-02-06 10:57:34 |
| 1        | 3         | hijk     | 2022-02-07 10:58:34 |
| 1        | 2         | lmop     | 2022-02-08 10:59:34 |


我试过了,但它给我的是当前登录用户每次对话的最后一条消息,而不是其他用户。

我最好使用 sql 来获取数据。首先你需要得到 created_at 的 Max 按 from_id 和 to_id 分组,然后在三个字段 from_id 上将结果连接到相同的 table,to_id 和 created_at。您还可以将用户 table 作为别名 (from_user/to_user)...

同时附加到 from_id 和 to_id

第一个查询给出 from_id、to_id、last_message_created_at:

SELECT 
    from_id, 
    to_id, 
    max(created_at) last_message_created_at 
FROM messages 
GROUP BY from_id, to_id

将结果与原始邮件 table 合并,如下所示。最后的 SQL 会是这样的。

SELECT
    from_user.id,
    to_user.id,
    msgs.message,
    msgs.created_at
    # add any additional field from msgs/from_user/to_user aliases as required
FROM messages msgs
JOIN (             #join the first query above here
    SELECT 
        from_id, 
        to_id, 
        max(created_at) last_message_created_at 
    FROM messages 
    GROUP BY from_id, to_id
) last_msgs ON
    (msgs.from_id = last_msgs.from_id
    AND msgs.to_id = last_msgs.to_id
    AND msgs.created_at = last_msgs.last_message_created_at)

JOIN users from_user on from_user.id = msgs.from_id
JOIN users to_user on to_user.id = msgs.to_id

使用Laravel 函数DB::select 将查询结果提取到数组中。将上面的sql字符串放入一个变量$sql

$results_array = DB::select($sql)

了解 DB::select here。您还可以使用参数化查询。

here是Laravel

中运行原始sql查询的一些示例

我用下面的代码得到了预期的输出。 我知道我的代码有一些改进,但现在可以正常使用。

$user_id = $request->user_id;
$user_name = DB::table('users')->where('id', $user_id)->value('name');

$chats =DB::table('messages')
                    ->leftJoin('users as u1', 'messages.from_id', '=', 'u1.id')
                    ->leftJoin('users as u2', 'messages.to_id', '=', 'u2.id')
                    ->select('u1.id as user_id', 'u1.name', 'u2.name as name2', 'messages.id','messages.from_id', 
                    'messages.to_id', 'messages.body as message', 'messages.attachment', 'messages.created_at')
                    ->where('messages.from_id', $user_id)
                    ->orWhere('messages.to_id', $user_id)
                    ->latest()
                    ->get();


foreach($chats as $chat)
        {
            $chat->user_id = $chat->from_id == $user_id ? $chat->to_id : $chat->from_id;
            $chat->name = $chat->name == $user_name ? $chat->name2 : $chat->name;
        }
        $chats = $chats->unique('user_id');