Dit lijkt een bug te zijn in MySQL, waarover ik een rapport heb ingediend . Ik heb het beperkt tot de volgende testcase, waarvan men zou verwachten dat het een enkel record zou retourneren (maar dat doet het niet):
CREATE TABLE t (x INT NULL); -- table with nullable column
INSERT INTO t VALUES (0); -- but non null data
SELECT a.x -- select our nullable column
FROM t a, (SELECT NULL) b -- joining it with anything at all
WHERE EXISTS ( -- but filter on a subquery
SELECT *
FROM (SELECT NULL) c -- doesn't really matter what
HAVING a.x IS NOT NULL -- provided there is some correlated condition
-- on our nullable column in the HAVING clause
)
ORDER BY RAND() -- then perform a filesort on the outer query
Bekijk het op sqlfiddle .
In jouw geval kun je een aantal dingen doen om dit op te lossen:
-
Vermijd de gecorreleerde subquery door te herschrijven als een join:
SELECT * FROM people AS p LEFT JOIN (people_stages AS s NATURAL JOIN ( SELECT person_id, MAX(created) created FROM people_stages GROUP BY person_id ) t) ON s.person_id = p.id ORDER BY p.last_name
-
Als u de gecorreleerde subquery wilt behouden (die over het algemeen slechte prestaties kan opleveren maar vaak gemakkelijker te begrijpen is), gebruikt u
WHERE
in plaats vanHAVING
:SELECT * FROM people AS p LEFT JOIN people_stages AS s ON s.person_id = p.id WHERE s.created = ( SELECT MAX(created) FROM people_stages WHERE person_id = s.person_id ) ORDER BY p.last_name
-
Als je de zoekopdracht niet kunt wijzigen, zou je moeten ontdekken dat het maken van de
people_stages.person_id
kolom non-nullable zal het probleem omzeilen:ALTER TABLE people_stages MODIFY person_id BIGINT UNSIGNED NOT NULL
Het lijkt erop dat het hebben van een index op die kolom (die nodig zou zijn om een externe sleutelbeperking te bewerkstelligen) ook kan helpen:
ALTER TABLE people_stages ADD FOREIGN KEY (person_id) REFERENCES people (id)
-
Als alternatief kan men
people_stages.person_id
. verwijderen uit de selectielijst, of pas het datamodel/indexering/query-strategie aan om een bestandssortering te vermijden (in dit geval misschien niet praktisch, maar ik vermeld ze hier voor de volledigheid).