Красноречивые групповые сообщения - PullRequest
1 голос
/ 28 марта 2020

Я играю с красноречивым Laravel и базой MYSQL

Мне нужно отобразить список разговоров, это моя структура таблицы

messages:
- id
- from_id
- to_id
- message
- read

|----|-----------|---------|-------|------|
| id | message   | from_id | to_id | read |  
|----|---------------------|--------------|
| 1  | hello     | 1       | 2     | 1    |
| 2  | hey       | 2       | 1     | 0    |
| 3  | there     | 2       | 1     | 0    |
| 4  | hi!       | 3       | 1     | 1    |
|----|-----------|---------|-------|------|

users:
- id
- name

|-----------|
| id | name |  
|-----------|
| 1  | john |
| 2  | mary | 
| 3  | jack | 
|-----------|

Ожидается:

если я пользователь 1 (должно отображаться последнее сообщение и количество непрочитанных сообщений

|----|------|---------|--------|
| id | name | message | unread |  
|----|------|---------|--------|
| 3  | mary | there   | 2      |  
| 4  | jack | hi!     | 0      |   
|----|------|-------- |--------|

Я не уверен, что это правильная структура таблицы для того, что я хочу сделать но SQL должно быть что-то вроде

SELECT users.name, messages.message
FROM users, messages
WHERE messages.from_id = 1 OR messages.to_id = 1
GROUP BY ??
ORDER BY messages.id DESC

Я не уверен, как группировать, потому что если я группирую по messages.from_id = 1, он будет показывать только отправленные мной сообщения, а не полученные сообщения. помогите мне вещь:)

также, как обрабатывать статус чтения? наверняка, атрибут чтения - это что-то вроде to_id, которое будет установлено в 1. как проверить это и в запросе?

1 Ответ

0 голосов
/ 30 марта 2020

Вот пару вещей, которые я вижу здесь. 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...