MySQL Различные результаты из одного и того же запроса / данных
У меня есть два сервера под управлением MySQL. Оба на окнах. Один из них - мой локальный компьютер (Windows 7, MySQL 5.6.25, 32-битный), а другой - мой рабочий веб-сервер (Windows 2012, MySQL 5.7.11-log, 64-битный (это то, что мне показывали переменные).
Данные идентичны между ними. Я скопировал данные из Windows 7 (используя MySQL Workbench) и восстановил их на компьютере 2012 года.
Я выполняю запрос на обеих машинах, но получаю разные результаты. У меня есть две таблицы, проекты и заметки проектов с отношением 1:m между ними, связанные с projects.id и projectsnotes.idProject. Каждая заметка отмечена датой (dComment). Цель запроса - получить информацию о проекте и только последний комментарий.
Вот запрос:
select space(1) as cAction,
p.id,
p.iNum,
p.cStatus,
p.cName,
p.cDesc,
ifnull(pl.cNickName, 'UNASSIGNED') as cProjectLeader,
IFNULL(concat (
date_format(pn.dComment, '%Y-%m-%d'),
': ',
pn.cComment
), '') as cComment,
date_format(p.dRequested, '%Y-%m-%d') as dRequested,
date_format(p.dRequired, '%Y-%m-%d') as dRequired,
format(p.nPercentComplete, 2) as nPercentComplete,
p.tLastUpdated,
p.bCompleted,
p.idProjectLeader
from projects p
left outer join projectleaders pl on p.idProjectLeader = pl.id
left outer join (
select idProject,
dComment,
cComment
from projectnotes
order by dComment desc,
tLastUpdated desc
) pn on p.id = pn.idProject
where p.cInstallCode = 'ITM'
and cStatus in ('Pending', 'Active', 'On Hold', 'Completed', 'Cancelled')
and bCompleted = 0
group by iNum
order by iNum;
Теперь вот странная часть. Когда я запускаю это на своем компьютере с Windows 7, я получаю правильное значение для cComment. В частности:
2017-03-28: текст из заметки заменить
Это последняя заметка. Когда я запускаю его на сервере 2012 года:
2016-05-17: текст этой заметки заменен
Если я запускаю один подзапрос на сервере 2012, я получаю правильные значения (а именно, список всех заметок в обратном порядке.
О, и эта заметка не является ни первой, ни последней в заметках к этому проекту.
Так что мне честно интересно, что происходит. Любые мысли по этому поводу будет принята с благодарностью.
Заранее спасибо.
2 ответа
Это ожидаемое поведение.
select ...
from projects p
left outer join projectleaders pl on p.idProjectLeader = pl.id
left outer join (...) pn on p.id = pn.idProject
where ...
group by iNum
order by iNum;
Из-за специфической обработки MySQL для GROUP BY он не будет сообщать об ошибке в этом запросе. Однако вы должны иметь в виду, что, поскольку вы не используете агрегаты, а GROUP BY удалит много строк, строки, которые хранятся в окончательном наборе результатов, определяются довольно неясными критериями...
Например:
SELECT a,b FROM t GROUP BY a
Какой б будет возвращен? В некоторых версиях MySQL это будет первое значение b, найденное в таблице t. Если таблица t упорядочена определенным образом, это можно использовать. Но я бы определенно не доверял этому поведению, чтобы оно оставалось неизменным между версиями... Кроме того, помните, что MySQL может свободно изменять порядок соединения...
ХОРОШО. Я думаю, что у меня есть решение этого. Вместо того чтобы делать это с помощью соединения, я написал функцию, которая возвращала нужное мне значение следующим образом:
DROP FUNCTION if exists f_lastprojectnote;
DELIMITER $$
CREATE FUNCTION f_lastprojectnote(tidProject varchar(36))
RETURNS varchar(1000) DETERMINISTIC
BEGIN
DECLARE cRetVal VARCHAR(1000);
SELECT concat(date_format(pn.dComment, '%Y-%m-%d'), ': ', pn.cComment) INTO cRetVal
FROM projectnotes pn
WHERE idProject = tidProject
ORDER BY dComment DESC, tLastUpdated DESC
LIMIT 1;
RETURN cRetVal;
END$$
DELIMITER ;
Оно работает...