-1

I have two MySQL tables - equipment and calibration, where equipment represents an inventory of equipment and calibration holds records for each equipment calibration. One equipment will have multiple calibrations.

In MySQL 5.5 the following query was fully working to identify equipment where the most recent calibration has expired:

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()

However in MySQL 5.7 the same SQL query works but returns rows including the oldest calibration not the most recent.

I've been experimenting with different joins but all need the GROUP BY facility and that seems to be where this all goes wrong.

While the above is a fictional example I have a lot of queries that are very similar in structure and behaving the same way. My question in two parts is:

  1. Why is this behaving differently in MySQL 5.7, and

  2. What changes do I need to make to the SQL to get it to function as desired in MySQL 5.7?

Thank you for your help.

GMB
  • 216,147
  • 25
  • 84
  • 135
richhallstoke
  • 1,519
  • 2
  • 16
  • 29
  • 1
    You have columns in the `SELECT` not in the `GROUP BY`. Your query is -- and always has been -- broken. I would suggest you ask another question and provide sample data, desired results, and an explanation of the logic so you can learn how to write a correct query to do what you want. – Gordon Linoff Apr 17 '20 at 15:55
  • Yous should read up on functional dependency in the manual. – P.Salmon Apr 17 '20 at 15:55
  • take some data and test your query in dbfiddle, which has only_full_group enabled, there you can see why your query is not ok. – nbk Apr 17 '20 at 15:58
  • Does this answer your question? [Error related to only\_full\_group\_by when executing a query in MySql](https://stackoverflow.com/questions/34115174/error-related-to-only-full-group-by-when-executing-a-query-in-mysql) – philipxy Apr 18 '20 at 02:22

1 Answers1

0

Your original query has non-aggregated columns in the select clause that do not belong to the group by clause. While MySQL might allow that, which value will be picked is actually undefined, meaning that it is not guaranteed to be consistent over consecutive executions.

Preventing developers from falling into this trap is one of the reason why MySQL enables ONLY_FULL_GROUP_BY by default starting version 5.7 (since your query is still running, it means that this sql mode was explicitly disabled in the configuration of your new database server).

If I understood your query correctly, you can use a correlated subquery instead:

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
GMB
  • 216,147
  • 25
  • 84
  • 135
  • Thanks for this, I've actually tried the correlated subquery approach but have so far been unable to get all the columns I needed. The pseduo code version of what I'm after would be something like this: fetch a list of all the equipment (all columns, exclude deleted equipment) with alongside it on the same row the columns of the most recent calibration record for that equipment, and with all results ordered in descending order by the due date of the next calibration. Any equipment with no prior calibrations shall still appear in the list but with NULL values for the calibration columns. Thanks – richhallstoke Apr 20 '20 at 10:42
  • @richhallstoke: it would help if you could provide a [db<>fiddle](https://dbfiddle.uk/) of some sort, with your sample data and expected results. – GMB Apr 20 '20 at 11:12
  • I'd love to but can't figure out how use db<>fiddle. Whatever I type in I just get run failed errors :( – richhallstoke Apr 20 '20 at 11:18
  • If I include all the columns in the GROUP BY statement it doesn't filter so that I only have one calibration per equipment. When working properly I should have only 3 rows with eqt 1 & cal 2, eqt 2 & cal 4, eqt 3 & cal 6 - https://www.db-fiddle.com/f/bEuUi76eJ5LjCwkTgzmAwU/0 – richhallstoke Apr 20 '20 at 12:46