sql >> Database >  >> RDS >> Mysql

Query retourneert alleen geen resultaten wanneer ORDER BY is toegevoegd

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:

  1. 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
    
  2. 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 van HAVING :

    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
    
  3. 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)
    
  4. 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).



  1. Voorloop- en volgtekens verwijderen in SQL Server

  2. Hoe IPv6 van binair te converteren voor opslag in MySQL

  3. MySQL diakritisch ongevoelig zoeken (Arabisch)

  4. Fout bij DECLARE-variabele in MySql-procedure