То есть по факту у Вас есть таблица сообщений между пользователями и Вам необходимо выбрать последнее сообщение в рамках каждого диалога.
Я вижу тут три варианта решения:
Вариант 1.
Если считать что последнее сообщение - это сообщение с большим идентификатором, тогда все последние сообщения по диалогу можно получить так
SELECT
*
FROM
chat
LEFT JOIN (
SELECT
max(id) AS message_id,
IF (`to` = 1, `from`, `to`) AS `collocutor_id`
FROM
chat
GROUP BY
`collocutor_id`
) AS m ON chat.id = m.message_id
WHERE
m.message_id IS NOT NULL
или так
SELECT
*
FROM
chat
WHERE
id IN (
SELECT
max(id) AS message_id
FROM
chat
GROUP BY
IF (`to` = 1, `from`, `to`)
)
Вариант 2.
Если считать что последнее сообщение - это сообщение с большей датой, тогда все последние сообщения по диалогу можно получить так
SELECT
chat.*
FROM
chat
LEFT JOIN (
SELECT
max(datetime) AS datetime,
IF (`to` = 1, `from`, `to`) AS `collocutor_id`
FROM
chat
GROUP BY
`collocutor_id`
) AS m ON (
m.`collocutor_id` = chat.`to`
OR m.`collocutor_id` = chat.`from`
)
AND chat.datetime < m.datetime
WHERE
m.datetime IS NULL
Но тут стоит понимать что если в рамках одного диалога совпадет дата и время - будет баг. Хотя и вероятность этого думаю крайнемала
Вариант 3.
Перепроектировать базу данных, а именно создать отдельную таблицу содержащую информацию о диалогах и работать непосредственно с ней. Это бы позволило избежать лишних запросов к БД