Sélection d'un interval d'après un tri

Talstus
Invité n'ayant pas de compte PHPfrance

04 mars 2006, 15:30

Bonjour
Je souterais faire une requête qui me permetrait d'avoir les résultats précédents et suivants le réponse à ma requête...
Un exemple sera surement plus clair que mon charabiat :roll:

Suposons que j'ai un table de ce type:
id lettre
------------
1 y
2 x
3 m
4 a
5 t
6 b
7 s
8 b

Je souhaite l'organiser par lettre, ce qui me donne:
id lettre
------------
4 a
8 b
6 b
3 m
7 s
5 t
2 x
1 y

Maintenant je voudrais ajouter un critère de sélection sur l'id 3, et j'aimerais pouvoir en même temps récupérer les informations des id 6 et 7, correspondant respectivement aux résultats précédents et suivants.

Jusque là je mettait tout mes résultats dans un tableau PHP et je me débrouillait avec ca, mais la table va prendre de l'ampleur et j'ai peur du résultat sur la rapidité :'(

Si quelqu'un a une sugestion, je suis preneur !

Modérateur PHPfrance
Modérateur PHPfrance | 7636 Messages

04 mars 2006, 16:01

Salut,

La pagination pourrai peut être convenir, regarde le tuto de la FAQ

/!\ Avant de poster se documenter et rechercher.
Qui ne sait pas rendre un service n'a pas le droit d'en demander.
MaBrute

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

05 mars 2006, 09:57

Avant toute chose, puisque ta table semble pouvoir avoir des ex-æquo il te faut définir un ordre unique. Pour l'exemple, on prendra "lettre, id". Je te conseille de définir l'ordre du champs de départage (le second champs pour trier les ex-æquo) identique au classement premier. En d'autres termes: tu devais utiliser "lettre ASC, id ASC" ou "lettre DESC, id DESC". Cela aura pour effet d'inverser la position des deux "b" de ton exemple, mais permettra à MySQL de faire un excellent usage de l'index que tu crééras sur "lettre, id".

Le classement intégral correspondant à ton exemple (mis à part le nouveau départage des deux "b") serait donc:

Code : Tout sélectionner

SELECT * FROM table ORDER BY lettre ASC, id ASC
Il n'y a pas de solution magique, le plus simple pour toi sera de récupérer l'enregistrement (id=3), puis le précédent, puis le suivant. Par exemple:

Code : Tout sélectionner

SELECT * FROM table WHERE id = 3

Code : Tout sélectionner

SELECT * FROM table /* précédent */ WHERE lettre < 'm' /* évidemment, le 'm' provient de la requête précédente */ OR (lettre = 'm' AND id < 3) ORDER BY lettre DESC, id DESC /* ordre inverse du classement intégral */ LIMIT 1

Code : Tout sélectionner

SELECT * FROM table /* suivant */ WHERE lettre > 'm' OR (lettre = 'm' AND id > 3) ORDER BY lettre ASC, id ASC LIMIT 1
D'autres solutions existent, mais elles seront généralement moins performantes. On pourrait obtenir la même chose en une seul requête, mais ça prendrait deux fois plus de temps que ces 3 requêtes.

Au fait, au cas où tu ne le saurais pas, ce qui se trouve entre /* et */ est ignoré par MySQL, ce sont des commentaires.

Talstus
Invité n'ayant pas de compte PHPfrance

07 mars 2006, 01:36

Merci à toi Truc, mais j'ai pas trouvé ma réponse dans la FAQ, en revanche la réponse de Hubert Roksor me plait beaucoups !
Je teste ca de mon côté, je vous tiend informés.

Merci encore pour votre aide, j'aurais certainement continué à mettre à rude épreuve mon serveur sasn ca! 8)

Talstus
Invité n'ayant pas de compte PHPfrance

08 mars 2006, 20:20

Ca marche parfaitement, encore merci Hubert

:agenouille: