web-dev-qa-db-fra.com

Comment fonctionne ORDER BY FIELD () dans MySQL fonctionne en interne

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

  • Comment cela fonctionne-t-il en interne?
  • Comment MySQL obtient-il les lignes et calcule-t-il l'ordre de tri?
  • Comment MySQL sait-il qu'il doit trier par la colonne id?
41
itz_nsn

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,

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.

  • Si la première colonne est 0, faites apparaître l'un des 4 premiers identifiants
  • Si la première colonne est 1, faites-la apparaître après

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 la première colonne est 1, faites tout sauf les 4 premiers identifiants.
  • Si la première colonne est 0, faites apparaître les 4 premiers identifiants dans l'ordre d'origine

VOTRE QUESTION RÉELLE

Si vous voulez sérieusement des internes à ce sujet, allez-y pages 189 et 192 du livre

MySQL Internals

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.

68
RolandoMySQLDBA

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.

1
jkavalik