简体   繁体   中英

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

i have two tables named users and message , I want to join both tables and get the last message from each user's conversation with user name.

I want last message by timestamp between two users whether it is from_id or to_id , and similarly, want last message from every user from which I had any conversation.

messages table having columns from_id, to_id, messages .

Below is my code.

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

My messages table is

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


I have tried this but it is giving me the last message of each conversation of current logged in user and not others.

I would ideally use sql to get the data. First you need to get the Max of created_at grouped by from_id and to_id, then join the results to the same table on the three fields from_id, to_id and created_at. You can also attach the users table to both from_id and to_id as aliases (from_user\/to_user)...

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

I got the expected output with the below code. I know there is some improvement in my code, but it is functional for now.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM