Вот пару вещей, которые я вижу здесь. 1. при агрегировании ваших данных для подсчета количества непрочитанных писем вы по-прежнему показываете хотя бы одно сообщение, в котором указан текст сообщения. В ожидаемом ответе:
|----|------|---------|--------|
| id | name | message | unread |
|----|------|---------|--------|
| 3 | mary | there | 2 |
| 4 | jack | hi! | 0 |
|----|------|-------- |--------|
У вас есть два непрочитанных сообщения для Мэри, однако в столбце сообщения указано there
, что является только сообщением одного из двух непрочитанных писем.
Я просто интересно, это специально.
Тем не менее, чтобы получить то, что вам нужно, go, у вас есть столбец read
, который выглядит двоичным по своей природе: 1 для прочитанных сообщений, 0 для непрочитанных сообщений.
При этом вы можете использовать этот лог c для подсчета количества непрочитанных сообщений, используя алгоритм: count(read) - sum(read)
.
Второе - это ваши объединения. Вы должны объединить таблицы, чтобы установить sh имена для user_ids. в вашем случае вы вообще не используете соединение, а фильтруете по полю. если вам нужен список
from
пользователей, отфильтрованный пользователями
to
, то вам нужно присоединить
from_id
к
user_id
, чтобы вы могли получить имя.
Там Вы можете группировать по имени и, по крайней мере, получить id, name, unread
. как в этом примере:
SELECT users.name, count(read) - sum(read) as unread
FROM users, messages
WHERE users.id = messages.from_id and messages.to_id = 1 --to me
GROUP BY users.name
ORDER BY messages.from_id ASC
в laravel ORM, попробуйте это (я знаю, что я близко, но я мобильн и не смог проверить это, так что поиграйте) :
$users = DB::table('messages')
->select(DB::raw('users.name, count(read) - sum(read) as unread'))
->join('users', 'users.id', '=', 'messages.from_id')
->where('to_id', '=', 1)
->orWhere('from_id', '=', '1')
->groupBy('users.name')
->orderBy('messages.from_id','ASC')
->get();
Попробуйте это.
ОБНОВЛЕНИЕ 1:
, чтобы преднамеренно получить "последнее" сообщение со списком:
select u.name, fm.message, count(m.unread) - sum(m.unread) as unread,
case when m.from_id = 1 then 'sent'
when m.to_id = 1 then 'received'
else null
end status
from messages m
join users u on u.id = m.from_id
left join (
Select max(id) as id, from_id, message from messages group by from_id
) fm on m.from_id = fm.from_id
where m.from_id = 1 or m.to_id = 1
group by u.name;
Eloquent :
DB::table('messages')
->select('u.name', 'fm.message', 'count(m.read) - sum(m.read) as unread', 'case when m.from_id = 1 then "sent" when m.to_id = 1 then "received" else null end status')
->join(users u', 'u.id', '=', 'u.from_id')
->leftjoin(DB::raw('Select max(id) as id, from_id, message from messages group by from_id', 'm.from_id', 'fm.from_id'))
->groupBy('users.name')
->orderBy('messages.from_id','ASC')
->get();