Вариант для MySQL ниже 8 версии:
select A.*
from
(
SELECT d.id AS dialog_id,
d.date_latest_message,
(select max(DM.added_date)
from dialog_messages dm3
where dm3.dialog_id = dm.dialog_id
) as datetime_latest_message,
Dm.Id as Dm_Id,
DM.message,
DM.added_date
FROM dialogs d
join dialog_messages dm on DM.dialog_id = D.dialog_id
WHERE (select count(*)
from dialog_messages dm2
where dm2.dialog_id = dm.dialog_id
and dm2.id > dm.id -- по идент. будет эффективнее работать, чем по дате-время, к тому же первичный ключ, как правило, проиндексирован, не требуется доп. индексов
) < 3 -- берем только те сообщения, которые позднее опубликованы чем текущее (3 вышестоящих)
and DATE(d.date_latest_message BETWEEN) '2020-10-01' AND '2021-10-08'
) A
order by A.datetime_latest_message desc, A.Dm_Id desc
Если MySQL версии 8 и выше, как вариант, можно взять оконную функцию
row_number.
select A.*
from
(
SELECT
d.id AS dialog_id,
d.date_latest_message,
(select max(DM.added_date)
from dialog_messages dm3
where dm3.dialog_id = dm.dialog_id
) as datetime_latest_message,
Dm.Id as Dm_Id,
DM.message,
DM.added_date AS message_added_date,
row_number() over (partition by d.id -- окно счетчика в пределах идент. диалога
order by DM.Id desc -- направление сортировки счетчика
) dm_rownum -- счетчик для отсечения порций
FROM dialogs d
join dialog_messages dm on DM.dialog_id = D.dialog_id
WHERE DATE(d.date_latest_message) BETWEEN '2020-10-01' AND '2021-10-08'
) A
where A.dm_rownum <= 3 -- отсекаем нужное число "локальных" отсчетов
ORDER BY A.datetime_latest_message DESC, A.Dm_Id DESC