Да, у вас есть проблема в вашем запросе.
Во-первых, вы должны были заметить, что подсчитываете столбец, который вы группируете, поэтому результат подсчета будет равен 1. Во-вторых, вы сравниваете метку времени сстрока: m.timestamp > 'p.last_read'
.Наконец, избегайте использования LIMIT
, когда вы знаете, что ваш запрос вернет одну строку (будьте уверены: p).
Попробуйте:
SELECT
COUNT(m.conversation_id) AS count
FROM
messages_message m
INNER JOIN
messages_participants p ON p.conversation_id = m.conversation_id
WHERE
m.timestamp > p.last_read
AND p.user_id = 5
, если вы хотите увеличить количество выполняемых запросоввремя, когда вы можете создать новый индекс в message_participants (journal_id, user_id), чтобы проиндексировать разговоры по пользователям, а затем изменить ваш запрос с помощью:
SELECT
COUNT(m.conversation_id) AS count
FROM
messages_message m
INNER JOIN
messages_participants p ON p.conversation_id = m.conversation_id AND p.user_id = 5
WHERE
m.timestamp > p.last_read
, чтобы ваш движок БД теперь мог фильтровать JOIN, просто посмотрев натаблица индексов.Вы можете углубиться в эту мысль, индексировав также временную метку: (timestamp, dialog_id, user_id) и поместите условие where в условие соединения.
Что бы вы ни выбрали, всегда сначала ставьте наиболее селективное поле, чтобы увеличитьселективность.
РЕДАКТИРОВАТЬ
Сначала прокомментируем ваш запрос:
SELECT
SQL_CALC_FOUND_ROWS c.*,
last_msg.*,
new_msgs.count as new_msgs_count
FROM
messages_conversation c
INNER JOIN
messages_participants p ON p.user_id = 5 -- Join with every conversations of user 5; if id is an integer, avoid writing '5' (string converted to an integer).
INNER JOIN
( -- Select every message : you could already select here messages from user 5
SELECT
*
FROM
messages_message m
ORDER BY -- this is not the goal of ORDER BY. Use MAX to obtain to latest timestamp.
m.timestamp DESC
LIMIT 1
) last_msg ON c.id = last_msg.conversation_id -- this query return one row and you want to have the latest timestamp for each conversation.
LEFT JOIN
(
SELECT
COUNT(m.id) AS count,
m.conversation_id,
m.timestamp
FROM
messages_message m
) new_msgs ON c.id = new_msgs.conversation_id AND new_msgs.timestamp > p.last_read
LIMIT 0,10
Перефразируем ваш запрос: выберите количество новых сообщений в теме разговора, его последнее сообщениеи отметка времени для пользователя @ id.
Делайте это шаг за шагом:
Выбор последнего сообщения, отметки времени в разговоре для каждого пользователя:
SELECT -- select the latest timestamp with its message
max(timestamp),
message
FROM
messages_message
GROUP BY
user_id
Агрегирует функции (MAX,MIN, SUM, ...) работают в текущей группе.Прочитайте это как «для каждой группы вычислите агрегатные функции, затем выберите то, что мне нужно, если мои условия выполняются».Так что это приведет к одному ряду на группу.Таким образом, этот последний запрос выбирает последнее сообщение и метку времени каждого пользователя в таблице messages_message.Как видите, это значение легко выбрать для конкретного пользователя, добавив предложение WHERE:
SELECT
MAX(timestamp),
message
FROM
messages_message
WHERE
user_id = @id
GROUP BY
user_id
Количество сообщений на разговор: для каждого разговора подсчитайте количество сообщений
SELECT
COUNT(m.id) -- assuming id column is unique, otherwise count distinct value.
FROM
messages_conversation c
INNER JOIN -- The current user participated to the conversation
messages_participant p ON p.conversation_id = c.id AND p.user_id = @id
OUTER JOIN -- Messages of the conversation where the current user participated, newer than last read its time
messages_message m ON m.conversation_id = c.id AND m.timestamp > p.last_read = @id
GROUP BY
c.id -- for each conversation
INNER JOIN
не возвращает строки для разговоров, в которых текущий пользователь не участвовал.Затем OUTER JOIN
объединится с NULL
столбцами, если условие ложно, поэтому COUNT вернет 0 - новых сообщений нет.
Собираем все вместе.
Выберите последнеесообщение и отметка времени в разговоре, в котором участвовал текущий пользователь, и количество новых сообщений в каждом разговоре.Это соединение между двумя последними запросами.
SELECT
last_msg.conversation_id,
last_msg.message,
last_msg.max_timestamp,
new_msgs.nb
FROM
(
SELECT
MAX(timestamp) AS max_timestamp,
message,
conversation_id
FROM
messages_message
WHERE
user_id = @id
GROUP BY
user_id
) last_msg
JOIN
(
SELECT
c.id AS conversation_id
COUNT(m.id) AS nb
FROM
messages_conversation c
INNER JOIN
messages_participant p ON p.conversation_id = c.id AND p.user_id = @id
OUTER JOIN
messages_message m ON m.conversation_id = c.id AND m.timestamp > p.last_read = @id
GROUP BY
C.id
) new_msgs ON new_msgs.conversation_id = last_msg.conversation_id
-- put here and only here a order by if necessary :)