Mysql
 sql >> Base de données >  >> RDS >> Mysql

La requête ne renvoie aucun résultat uniquement lorsque ORDER BY est ajouté

Cela semble être un bogue dans MySQL, à propos duquel j'ai rapporté . Je l'ai réduit au cas de test suivant, dont on s'attendrait à ce qu'il renvoie un seul enregistrement (mais ce n'est pas le cas) :

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

Voir sur sqlfiddle .

Dans votre cas, vous pouvez faire un certain nombre de choses pour résoudre ce problème :

  1. Évitez la sous-requête corrélée en réécrivant en tant que jointure :

    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. Si vous souhaitez conserver la sous-requête corrélée (qui peut généralement donner des performances médiocres mais est souvent plus facile à comprendre), utilisez WHERE au lieu de 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. Si vous ne parvenez pas à modifier la requête, vous devriez constater que la création du people_stages.person_id la colonne non-nullable contournera le problème :

    ALTER TABLE people_stages MODIFY person_id BIGINT UNSIGNED NOT NULL
    

    Il semble que le fait d'avoir un index sur cette colonne (ce qui serait nécessaire pour effectuer une contrainte de clé étrangère) puisse également aider :

    ALTER TABLE people_stages ADD FOREIGN KEY (person_id) REFERENCES people (id)
    
  4. Alternativement, on pourrait supprimer people_stages.person_id dans la liste de sélection, ou ajustez le modèle de données/l'indexation/la stratégie de requête pour éviter un tri de fichiers (peut-être pas pratique dans ce cas, mais je les mentionne ici pour être complet).