Je comprends le fonctionnement de la clause ORDER BY
Et le fonctionnement de la fonction FIELD()
. Ce que je veux comprendre, c'est comment les deux travaillent ensemble pour trier. Comment les lignes sont-elles récupérées et comment est dérivé l'ordre de tri
+----+---------+
| id | name |
+----+---------+
| 1 | stan |
| 2 | kyle |
| 3 | kenny |
| 4 | cartman |
+----+---------+
SELECT * FROM mytable WHERE id IN (3,2,1,4) ORDER BY FIELD(id,3,2,1,4)
La requête ci-dessus entraînera
+----+---------+
| id | name |
+----+---------+
| 3 | kenny |
| 2 | kyle |
| 1 | stan |
| 4 | cartman |
+----+---------+
quelque chose de similaire à dire ORDER BY 3, 2, 1, 4
DES QUESTIONS
Pour mémoire
SELECT * FROM mytable WHERE id IN (1,2,3,4) ORDER BY FIELD(id,3,2,1,4);
devrait également fonctionner car vous n'avez pas besoin de classer la liste dans la clause WHERE
Quant à la façon dont cela fonctionne,
FIELD () est une fonction qui renvoie la position d'index d'une liste délimitée par des virgules si la valeur que vous recherchez existe .
Les valeurs ORDER BY
Sont évaluées par ce que FIELD () renvoie
Vous pouvez créer toutes sortes de commandes fantaisies
Par exemple, en utilisant la fonction IF ()
SELECT * FROM mytable
WHERE id IN (1,2,3,4)
ORDER BY IF(FIELD(id,3,2,1,4)=0,1,0),FIELD(id,3,2,1,4);
Cela fera apparaître les 4 premiers identifiants en haut de la liste, sinon, ils apparaissent en bas. Pourquoi?
Dans le ORDER BY
, Vous obtenez soit 0 soit 1.
Tournons-le avec DESC dans la première colonne
SELECT * FROM mytable
WHERE id IN (1,2,3,4)
ORDER BY IF(FIELD(id,3,2,1,4)=0,1,0) DESC,FIELD(id,3,2,1,4);
Dans le ORDER BY
, Vous obtenez toujours 0 ou 1.
Si vous voulez sérieusement des internes à ce sujet, allez-y pages 189 et 192 du livre
pour une vraie plongée profonde.
En substance, il existe une classe C++ appelée ORDER *order
(L'arbre d'expression ORDER BY
). Dans JOIN::prepare
, *order
Est utilisé dans une fonction appelée setup_order()
. Pourquoi au milieu de la classe JOIN
? Chaque requête , même une requête sur une seule table est toujours traitée comme une JOIN (Voir mon article Y a-t-il une différence d'exécution entre une condition JOIN et une condition WHERE? )
Le code source de tout cela est sql/sql_select.cc
Evidemment, l'arborescence ORDER BY
Va contenir l'évaluation de FIELD(id,3,2,1,4)
. Ainsi, les nombres 0,1,2,3,4 sont les valeurs triées tout en portant une référence à la ligne impliquée.
Peut-être que ce sera trop loin du code réel, donc pas assez bas de ce que vous vouliez:
Lorsque MySQL ne peut pas utiliser l'index pour récupérer des données dans un ordre trié, il crée une table/un ensemble de résultats temporaire avec toutes les colonnes sélectionnées et certaines données supplémentaires - l'une d'entre elles est une sorte de colonne pour stocker les résultats de la valeur d'expression ORDER BY pour chaque ligne - puis il envoie cette table tmp à une rutine "filesort" avec des informations sur la colonne à trier. Après cela, les lignes sont triées afin de pouvoir les sélectionner une par une et renvoyer les colonnes sélectionnées.