Bonjour
Je voudrais trouver la solution à un problème qui se trouve à la base de beaucoup de questions soulevées par les utilisateurs de SQL.
En gros on peut le réduire à la question suivante :
Comment formuler la requête SQL pour extraire un enregistrement qui est le suivant par rapport à un autre enregistrement point de vue d’un index ?
Pour être plus clair je vais me servir d’un exemple.
J’ai une table "matable" avec l’index "monindex".
"monindex" est composé de deux champs (champ_clef1,champ_clef2).
champ_clef1, champ_clef2 sont de type INTEGER (pour simplifier).
"matable" contient les enregistrements suivants (triés selon "monindex") :
champ_clef1 -- champ_clef2
----- 1 --------- 1 --------
----- 1 --------- 2 --------
----- 1 --------- 3 --------
----- 2 --------- 1 --------
----- 2 --------- 2 --------
----- 2 --------- 3 --------
----- 3 --------- 1 --------
----- 3 --------- 2 --------
----- 3 --------- 3 --------
Je veux récupérer l’enregistrement qui se trouve juste après (1,3) - donc (2,1)…
J’ai essayé la requête :
A première vue ça marche mais en ajoutant "EXPLAIN" devant j’ai constaté que :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 SELECT * FROM matable FORCE INDEX monindex WHERE (champ_clef1,champ_clef2) > (1,3) LIMIT 1;
- aucun index était utilisé (SQL analyse tous les enregistrements)
- il y un risque que le résultat dépend du hasard. Comme l’index n’est pas utilisé, le premier enregistrement trouvé (je ne demande que un) pourrait être (3,3)
Ensuite j’ai essayé une autre requête :
Cette fois monindex était utilisé mais SQL malgré tout analysait plusieurs enregistrements au lieu de s’arrêter sur le premier trouvé. Après la lecture de la documentation j’ai compris que SQL a créé dans ce cas deux intervalles (à cause de "OR") et le résultat c’est la concaténation de ces intervalles ou plutôt le premier enregistrement de cette concaténation. Ici c’est pareil – ce n’est peut-être pas l’enregistrement que je cherche…
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 SELECT * FROM matable WHERE champ_clef1=1 AND champ_clef2>3 OR champ_clef1>1 LIMIT 1;
Pour être sûr il faudrait ajouter "ORDER BY champ_clef1, champ_clef2" à cette requête…
Bien, mais dans ce cas, SQL en interne va faire probablement un travail énorme (chaque intervalle peut comporter beaucoup d’enregistrements et tout ça il faut trier à la fin).
En bref, pour quelque chose qui paraît assez simple (en utilisant l’index il est théoriquement possible de trouver le bon enregistrement tout suite), on risque d’attendre la réponse longtemps.
Est-ce que quelqu’un pourrait m’aider ?
Partager