SQL-запрос для потоковых сообщений

Мой сайт имеет функцию обмена сообщениями, где один пользователь может отправлять сообщения другому. Сообщения поддерживают многопоточность - родительское сообщение может иметь любое количество дочерних элементов, но только один уровень.

Таблица сообщений выглядит так:

Messages
 - Id (PK, Auto-increment int)
 - UserId (FK, Users.Id)
 - FromUserId (FK, Users.Id)
 - ParentMessageId (FK to Messages.Id)
 - MessageText (varchar 200)

Я хотел бы показывать сообщения на странице с каждым "родительским" сообщением, за которым следует свернутый просмотр дочерних сообщений.

Могу ли я использовать предложение GROUP BY или аналогичную конструкцию для извлечения родительских и дочерних сообщений в одном запросе? Сейчас я получаю только родительские сообщения, затем перебираю их и выполняю еще один запрос для каждого, чтобы получить все связанные дочерние сообщения.

Я хотел бы получить такие сообщения:

Parent1
 Child1
 Child2
 Child3
Parent2
 Child1
Parent3
 Child1
 Child2

2 ответа

Решение

Вы можете использовать временный идентификатор для заказа сообщений. Если сообщение является родительским, то временный идентификатор будет равен идентификатору, иначе временный идентификатор будет равен ParentMessageID. Тогда вам просто нужно заказать по временному идентификатору

SELECT Messages.*, 
CASE WHEN ParentMessageId IS NULL THEN Id ELSE ParentMessageId END AS tempId 
FROM Messages
ORDER BY tempId

редактировать

Если вы хотите первые 10 записей, вы можете сначала получить идентификаторы, а затем выполнить запрос

SELECT Messages.*, 
CASE WHEN ParentMessageId IS NULL THEN Id ELSE ParentMessageId END AS tempId 
FROM Messages
WHERE Messages.tempId IN (SELECT Messages.Id 
                      FROM Messages
                      WHERE ParentMessageId IS NULL
                      LIMIT 10
                      ORDER BY Messages.Id )
ORDER BY tempId

Таким образом, вы получаете сообщения и соответствующие дочерние элементы только из первых 10 сообщений.

Попробуй это. Вы можете заменить range_, используя некоторую переменную, хранящуюся на вашем интерфейсе для нумерации страниц.

select child.MessageText from
(select @i:=@i+1 as range_, id, MessageText from messages, (select @i:=0) k where ParentMessageId is null order by id asc) parent 
left outer join messages child on (parent.id = child.ParentMessageId or parent.id = child.id)
where parent.range_ between 1 and 3;
Другие вопросы по тегам