Почему бы вам не отделить взаимосвязи между сообщениями и просмотром пользователем каждого сообщения?
Я бы сделал потоковую обработку с помощью самообращающихся ссылок на сообщение.Другими словами, в сообщении есть столбец «responseding_to_message_id».
Я не уверен, что понимаю, почему у вас "to_id".Направлены ли сообщения отдельным пользователям?Это кажется очень ограниченным.Я бы подумал, что у вас либо не будет получателя (то есть получатель - это доска объявлений, которую может прочитать каждый), либо у вас будет возможность указать несколько получателей, как в случае электронной почты.Возможно, вы сможете объяснить больше о том, как должна использоваться система.
Предполагая (для простоты), что вы публикуете сообщение на доске, поэтому важно только "от", тогда у вас есть таблица сообщений ссамореферентные отношения для потоков, пользовательской таблицы, а затем таблицы пересечений между пользователем и сообщением, в котором хранятся сообщения, которые были прочитаны каждым пользователем.
Таким образом, если вы хотите узнать, прочитал ли пользователь информацию.сообщение или нет, просто попытайтесь прочитать идентификатор пользователя в таблице пересечений для данного сообщения.Если там нет , то это сообщение не будет прочитано этим пользователем.
Обратите внимание, что если вы хотите, чтобы один получатель имел этот дизайн, и если вы хотите иметь несколько получателей, вы можетеиспользуйте таблицу пересечений для хранения списка получателей для каждого сообщения.Если у вас есть таблица пересечения получателей, она может выполнять двойную функцию в качестве таблицы состояния чтения.
РЕДАКТИРОВАТЬ: Эскиз ERD:
Вот быстрый набросоко чем я говорю ...
Независимо от того, выбрал ли отправитель сохранение сообщения, он помечен в самом сообщении.Если сообщение является началом нового потока, столбец reply_to_message_id имеет значение NULL, в противном случае это message_id родительского сообщения.Может быть несколько получателей, каждый из которых имеет свою собственную возможность сохранять сообщение или нет, а также возможность отслеживать дату и время, когда получатель читает сообщение.
РЕДАКТИРОВАТЬ 2:Альтернативный ERD и запрос самого последнего сообщения
@ OP спросил, как запросить самое последнее сообщение в цепочке.Ответ зависит от формы потока.У вас может быть либо плоский поток, в котором каждое сообщение идет до конца линейного потока сообщений, либо у вас может быть поток в форме дерева, где у каждого сообщения есть определенный родительский элемент, если только он не является корнем потока.В приведенной выше ERD поле response_to_message_id может использоваться в любом случае.Если нить плоская, то FK всегда находится в корневом СООБЩЕНИИ.Если поток имеет древовидную форму, то FK является непосредственным родителем ответа MESSAGE.
Если типичный запрос, который вы хотите выполнить, это «какое последнее сообщение в ветке?»и ваши потоки плоские, тогда вы можете использовать SQL следующим образом:
select top 1
M.message_id
, M.sent_datetime
, M.title
, M.message_text
, S.user_id
, S.user_name
-- and anything else you want...
from MESSAGE M inner join USER S
on M.sender_user_id = U.user_id
where M.reply_to_message_id = @ThreadRootMessageID
order by
M.sent_datetime desc
Если, с другой стороны, ваши потоки имеют древовидную форму, и это запрос, который вы хотите быстро выполнять илегко, тогда с схемой в ERD выше не очень легко работать.SQL не хорош в деревьях.Вы можете решить проблему с небольшой денормализацией.См. ERD ниже:
Обратите внимание, что теперь есть один FK, чтобы показать непосредственного родителя, и один FK, чтобы показать корень.Поскольку потоки не подлежат редактированию - по крайней мере, правкам, в которых корень сообщения изменяется так, чтобы он указывал на другой поток, связанная с этим денормализация не подразумевает риск возникновения аномалий обновления, поэтому избыточность не слишком проблематична.
Если вы используете эту ERD, тогда запрос «самое последнее сообщение в потоке X» будет таким же, как и выше, но с M.thread_root_message_id в предложении where вместо M.reply_to_message_id.