Итак, сначала вы объединяете свои сообщения в один запрос:
select `content`, `date`, id as m_id, id_chat, id_user_from, id_user_to,
null as p_id, null as id_page_chat, null as id_user, null as id_page, null as `from`
from message
union all
select `content`, `date`, null as m_id, null as id_chat, null as id_user_from, null as id_user_to,
id as p_id, id_page_chat, id_user, id_page, `from`
from page_message
Затем вы можете использовать это в качестве базовой таблицы для своего запроса, чтобы искать самое последнее сообщение из каждого разговора.(Этот код был бы намного чище, если бы вы использовали приведенный выше запрос для создания представления и ссылались на него вместо этого.)
select *
from (select `content`, `date`, id as m_id, id_chat, id_user_from, id_user_to,
null as p_id, null as id_page_chat, null as id_user, null as id_page, null as `from`
from message
union all
select `content`, `date`, null as m_id, null as id_chat, null as id_user_from, null as id_user_to,
id as p_id, id_page_chat, id_user, id_page, `from`
from page_message) m1
join
(select max(m_id) as m_id, max(p_id) as p_id
from (select `content`, `date`, id as m_id, id_chat, id_user_from, id_user_to,
null as p_id, null as id_page_chat, null as id_user, null as id_page, null as `from`
from message
union all
select `content`, `date`, null as m_id, null as id_chat, null as id_user_from, null as id_user_to,
id as p_id, id_page_chat, id_user, id_page, `from`
from page_message) all_msgs
where $userId IN (id_user_from, id_user_to, id_user)
AND IFNULL(id_chat, id_page_chat) NOT IN (".implode(",", $idsChat).")
group by id_chat, id_page_chat
order by m_id desc, p_id desc
) m2 on (m1.m_id = m2.m_id or m1.p_id = m2.p_id)
sqlfiddle