MySQL запрос с GROUP BY ведет себя по-разному между MySQL версиями? - PullRequest
0 голосов
/ 17 апреля 2020

У меня есть две таблицы MySQL - оборудование и калибровка, где оборудование представляет собой инвентарь оборудования, а калибровка содержит записи для каждой калибровки оборудования. Одно оборудование будет иметь несколько калибровок.

В MySQL 5.5 следующий запрос полностью работал для определения оборудования, у которого истек срок последней калибровки:

SELECT * FROM equipment AS e
LEFT JOIN (
  SELECT calibration_id, equipment_id, calibration_company, certificate_no, date_certified, date_nextdue
  FROM (
    SELECT calibration_id, equipment_id, calibration_company, certificate_no, date_certified, date_nextdue
    FROM calibration
    WHERE deleted=0
    ORDER BY date_certified DESC
  ) AS a GROUP BY a.equipment_id
) AS c ON c.equipment_id=e.equipment_id
WHERE e.deleted=0 AND c.date_nextdue <= CURRENT_DATE()

Однако в MySQL 5.7 тот же самый запрос SQL работает, но возвращает строки, включающие самую старую калибровку, а не самую последнюю.

Я экспериментировал с различными объединениями, но все нуждаются в возможности GROUP BY, и, похоже, именно здесь все идет не так, как надо. .

Хотя приведенный выше пример вымышлен, у меня есть много запросов, которые очень похожи по структуре и ведут себя одинаково. Мой вопрос состоит из двух частей:

  1. Почему это ведет себя по-разному в MySQL 5.7 и

  2. Какие изменения мне нужно внести? на SQL, чтобы заставить его функционировать как нужно в MySQL 5,7?

Спасибо за вашу помощь.

1 Ответ

0 голосов
/ 17 апреля 2020

Ваш исходный запрос содержит неагрегированные столбцы в предложении select, которые не принадлежат предложению group by. Хотя MySQL может разрешить это, то, какое значение будет выбрано, на самом деле не определено, что означает, что оно не гарантируется согласованным в течение последовательных выполнений.

Предотвращение попадания разработчиков в эту ловушку - одна из причин, по которой MySQL по умолчанию включает ONLY_FULL_GROUP_BY, начиная с версии 5.7 (поскольку ваш запрос все еще выполняется, это означает, что этот режим sql явно отключен в конфигурации вашего нового сервера базы данных).

Если я правильно понял ваш запрос, вы можете использовать вместо этого коррелированный подзапрос:

select e.*
from equipments e
where (
    select max(c.date_certified) 
    from calibration c 
    where c.equipment_id = e.equipment_id and c.deleted = 0
) <= current_date
...