Выборка из нескольких таблиц с сортировкой по времени каждой из них
Немного упрощу таблицы. У меня есть 6 таблиц.
- modemsInfo(id, idUser, idGroup, infoText) // информация о модемах
- groupModems(id, idUser, nameGroup) // информация о группах в которой могут быть модемы
- data(idModem, Time, text) // общая информация которую прислали модемы
- dataResponseConfig(idModem, Time, text) // конфигурационная инфа пришедшая от модемов
- dataResponseReset(idModem, Time, text) // результаты сбросов пришедшие от модемов
- queueSmsLog(idModem, Time, text) // смс которые отправлялись модемам
Мне нужно выдать инфу от модемов пользователя. Я выбираю модем и приклеиваю к нему последний ответ (сортирую в колонке(Time) и ставлю Limit 1) из таблиц: общий(data), конфига(dataResponseConfig), сброса(dataResponseReset) и смсЛога(queueSmsLog). Все работает до момента пока нет одинаковых значений времени(Time) в любой таблице. Появляются дубликаты. Использую такой запрос. Чувствую, что проблема в конце запроса, но как исправить уже знаний не хватает.
SELECT gM.nameGroup as nameGroup, mI.infoText, qSL.Time, qSL.text,
dRC.Time ,dRR.Time, data.Time, data.text
FROM groupModems gM
left outer JOIN modemsInfo mI ON mI.idUser = gM.idUser AND mI.idGroup = gM.id
left outer JOIN data ON mI.id = data.idModem
left outer JOIN queueSmsLog qSL ON mI.id = qSL.idModem
left outer JOIN dataResponseConfig dRC ON mI.id = dRC.idModem
left outer JOIN dataResponseReset dRR ON mI.id = dRR.idModem
WHERE gM.idUser = :user_id
AND (data.Time = (SELECT `Time`
FROM data
WHERE mI.id = data.idModem
ORDER BY `Time` DESC
LIMIT 1)
OR data.Time IS NULL)
AND (dRC.Time = (SELECT `Time`
FROM dataResponseConfig
WHERE mI.id = dataResponseConfig.idModem
ORDER BY `Time` DESC
LIMIT 1)
OR dRC.Time IS NULL)
AND (dRR.Time = (SELECT `Time`
FROM dataResponseReset
WHERE mI.id = dataResponseReset.idModem
ORDER BY `Time` DESC
LIMIT 1)
OR dRR.Time IS NULL)
AND (qSL.Time = (SELECT `Time`
FROM queueSmsLog
WHERE mI.id = queueSmsLog.idModem
ORDER BY id DESC
LIMIT 1)
OR qSL.Time IS NULL)
IS NULL - использовал на случай если вообще нет никакой информации в таблицах c ответами от модемов
Ответы (1 шт):
Если предположить, что в таблицах вроде dataResponseConfig есть собственные id записей (а куда же без них, если вдруг нет, добавьте), то выходит что то такое:
SELECT gM.nameGroup as nameGroup, mI.infoText,
qSL.Time, qSL.text,
(SELECT max(`Time`) FROM dataResponseConfig dRC WHERE mI.id = dRC.idModem) as dRC_Time,
(SELECT max(`Time`) FROM dataResponseReset dRR WHERE mI.id = dRR.idModem) as dRR_Time,
data.Time, data.text
FROM groupModems gM
left outer JOIN modemsInfo mI ON mI.idUser = gM.idUser AND mI.idGroup = gM.id
left outer JOIN data ON mI.id = data.idModem
left outer JOIN queueSmsLog qSL ON mI.id = qSL.idModem
WHERE gM.idUser = :user_id
AND ( (data.Time, data.id) = (SELECT `Time`, id FROM data
WHERE mI.id = data.idModem
ORDER BY `Time` DESC, id desc LIMIT 1)
OR data.Time IS NULL)
AND ( (qSL.Time, qSL.id) = (SELECT `Time`, id FROM queueSmsLog
WHERE mI.id = queueSmsLog.idModem
ORDER BY `Time` DESC, id DESC LIMIT 1)
OR qSL.Time IS NULL)
P.S. Если все именно так, как описана структура таблиц в вопросе и колонки id нет, то ее стоит добавить, работать с записями без явной уникальности крайне сложно. Тут конечно есть варианты вытаскивать что то вроде select max(concat(привести_к_строке(Time), text)) ... и потом обратно разбирать объединенную строку на time и text, но это довольно громоздко выглядит и вообще не удобно.