Я строю небольшую систему обмена сообщениями для своего приложения, основная идея — иметь 2 таблицы.
Table1 сообщения
Id,sender_id,title,body,file,parent_id
Здесь хранятся сообщения, отделенные от того, кто их получит, чтобы разрешить нескольким получателям.
Родитель, я бы связался с родительским сообщением, если оно является ответом, а файл является блобом для хранения одного файла, прикрепленного к сообщению.
Таблица 2 message_users
Id,thread_id,user_id,is_read,stared,deleted
Связать родительский поток с целевыми пользователями,
Теперь для одного пользователя, чтобы получить количество непрочитанных сообщений я могу сделать
Select count(*) from message_users where user_id = 1 and is_read is null
Чтобы подсчитать все сообщения в своем почтовом ящике я могу сделать
Select count(*) from message_users where user_id = 1;
Вопрос в том, как объединить оба в одном оптимизированном запросе?
Таким образом, вы пытаетесь достичь чего-то, что будет содержать строки, соответствующие одному условию, и общее количество строк, удовлетворяющих дополнительному условию:
|---------|---------|
| total | unread |
|---------|---------|
| 20 | 12 |
|---------|---------|
Как таковой понадобится что-то с формой в соответствии с:
SELECT A total, B unread FROM message_users WHERE user_id=1
A
довольно просто, у вас уже более или менее есть это: COUNT(Id)
,
B
немного сложнее и может принять форму SUM( IF(is_read IS NULL,1,0) )
— добавьте 1 каждый раз, когда is_read не равен нулю; условие будет зависеть от вашей базы данных.
Или же B
может выглядеть так: COUNT(CASE WHEN is_read IS NULL THEN 1 END) unread
— это говорит «когда is_read равен нулю, считай еще 1»; условие будет зависеть от вашей базы данных.
В целом:
SELECT COUNT(Id) total, COUNT(CASE WHEN is_read IS NULL THEN 1 END) unread FROM message_users WHERE user_id=1
Или же:
SELECT COUNT(Id) total, SUM( IF(is_read IS NULL,1,0) ) unread FROM message_users WHERE user_id=1
С точки зрения оптимизации, я не знаю о запросе, который обязательно может быть выполнен быстрее, чем этот. (Хотелось бы знать об этом, если он существует!) Могут быть способы ускорить процесс, если у вас есть проблемы с производительностью:
EXPLAIN
и некоторое чтение вокруг и т. д.unread_messages
против user
и получить это значение напрямую. Очевидно, что потребуется некоторая недействительность при записи или действительно какая-то служба, работающая для поддержания этих значений в актуальном состоянии. Есть много способов достичь этого, инструменты в MySQL, собственные руки и т. Д. И т. Д.В MySQL при подсчете поля он учитывает только ненулевые вхождения этого поля, поэтому вы должны иметь возможность сделать что-то вроде этого:
SELECT COUNT(user_id), COUNT(user_id) - COUNT(is_read) AS unread
FROM message_users
WHERE user_id = 1;
Не проверено, но оно должно указывать вам в правильном направлении.
Вы можете использовать сумму с CASE WHEN
пункт. Если is_read
тогда ноль +1
добавляется к сумме, иначе +0
,
SELECT count(*),
SUM(CASE WHEN is_read IS NULL THEN 1 ELSE 0 END) AS count_unread
FROM message_users WHERE user_id = 1;