Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Die Abfrage gibt nur dann keine Ergebnisse zurück, wenn ORDER BY hinzugefügt wurde

Dies scheint ein Fehler in MySQL zu sein, über den ich einen Bericht eingereicht . Ich habe es auf den folgenden Testfall eingegrenzt, von dem man erwarten würde, dass er einen einzelnen Datensatz zurückgibt (aber das tut er nicht):

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

Sehen Sie es auf sqlfiddle .

In Ihrem Fall können Sie eine Reihe von Maßnahmen ergreifen, um dies zu beheben:

  1. Vermeiden Sie die korrelierte Unterabfrage, indem Sie als Join umschreiben:

    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. Wenn Sie die korrelierte Unterabfrage beibehalten möchten (was im Allgemeinen zu einer schlechten Leistung führen kann, aber oft einfacher zu verstehen ist), verwenden Sie WHERE statt 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. Wenn Sie die Abfrage nicht ändern können, sollten Sie das finden, indem Sie people_stages.person_id erstellen Spalte, die keine Nullwerte zulässt, umgeht das Problem:

    ALTER TABLE people_stages MODIFY person_id BIGINT UNSIGNED NOT NULL
    

    Es scheint, dass es auch hilfreich sein kann, einen Index für diese Spalte zu haben (der erforderlich wäre, um eine Fremdschlüsseleinschränkung zu bewirken):

    ALTER TABLE people_stages ADD FOREIGN KEY (person_id) REFERENCES people (id)
    
  4. Alternativ könnte man people_stages.person_id entfernen aus der Auswahlliste, oder passen Sie die Datenmodell-/Indizierungs-/Abfragestrategie an, um eine Dateisortierung zu vermeiden (in diesem Fall möglicherweise nicht praktikabel, aber ich erwähne sie hier der Vollständigkeit halber).