Sélectionner les 5 plus proches produits

WRInaute passionné
Salut à tous,

Je cherche une requête mysql qui pourrait sélectionner dans une table les 5 produits le plus proche d'un produit.

En fonction du n° de produit qui sert de référence, il se peut parfois qu'il n'y ai pas (ou pas assez) de produits après ce produit, parce que c'est le dernier de la liste ou bien parce qu'il n'y a que 1, 2, 3 ou 4 produits après ce produit (et pas 5)... dans ce cas là il faudrait ajouter les 1,2, 3, 4 produits qui sont juste après ce produit et ajouter les autres produits qui sont juste avant ce produit pour arriver au total à 5 produits.

Voici un tableau pour illustrer le problème :
Code:
Num    Marque    Modele    Moteur    Couleur
1    peugeot    2008    diesel    blanc
2    peugeot    2008    diesel    rouge
3    peugeot    2008    diesel    bleu
4    peugeot    2008    diesel    noir
5    peugeot    2008    diesel    vert
6    peugeot    2008    diesel    orange
7    peugeot    2008    diesel    marron
8    peugeot    2008    diesel    jaune
9    peugeot    2008    essence    blanc
10    peugeot    2008    essence    rouge
11    peugeot    2008    essence    bleu
12    peugeot    2008    essence    noir
13    peugeot    2008    essence    vert
14    peugeot    2008    essence    orange
15    peugeot    2008    essence    marron
16    peugeot    2008    essence    jaune
17    renault    clio    diesel    blanc
18    renault    clio    diesel    rouge
19    renault    clio    diesel    bleu
20    renault    clio    diesel    noir
21    renault    clio    diesel    vert
22    renault    clio    diesel    orange
23    renault    clio    diesel    marron
24    renault    clio    diesel    jaune
25    renault    megane    essence    blanc
26    renault    megane    essence    rouge
27    renault    megane    essence    bleu
28    renault    megane    essence    noir
29    renault    megane    essence    vert
30    renault    megane    essence    orange
31    renault    megane    essence    marron
32    renault    megane    essence    jaune

Si le n° de produit est le 3 (peugeot 2008 diesel bleu), la requête devra sortir les 5 produits suivants : les n° 4, 5, 6, 7 et 8 parce qu'il s'agit toujours d'une "peugeot 2008 diesel" et qu'il existe bien 5 produits après le n° 3.

Mais si le n° de produit est le 15 (peugeot 2008 essence marron), la requête devra sortir les 5 n° suivants : le n° 16 puis les n° 14, 13, 12 et 11.

Je ne sais pas si je suis bien clair, si c'est pas le cas dites moi.

Voyez-vous une requête mysql qui puisse faire le job ?

Merci d'avance pour votre aide.
 
WRInaute passionné
Je ne vois pas de requête qui ferait ça, il faut en faire une qui sort tous les enregistrements qui ont les mêmes Marque et Modele, et descendre ou remonter le curseur en faisant une boucle en PHP.
 
WRInaute passionné
Merci pour ta réponse.

Je ne vois pas non plus de requête qui pourrait aller, bon ben c'est pas grave, je vais me débrouiller et trouver une solution.
 
WRInaute accro
Je ne ferais pas ça en mysql, mais en php...

En tout cas si je reformule bien ta demande :

Tu as une table avec des modèles de voitures, classés par
1- marque
2- modèle
3- motorisation
4- couleur
et l'ordre est important

Quand tu as une id produit, tu veux afficher les 4 produits suivants, et si tu n'as pas 4 produits, tu repars en arrière dans la liste.

1- première requete
select * from table_produit where (marque = "toto" & modele = "titi" and.
"motorisation" = "tata" and Num >= 25) order by Num asc limit 1,5

2- tu fais un petit count...

3- si tu as 5 voitures, c'est bon, sinon tu retournes dans ta table et tu fais la même sélection pour le nombre qui te manque, cette fois - ci en triant par Num desc avec un limit au nombre d'éléments qui te manquent

3- et tu fais l'union entre tes deux résultats
 
Nouveau WRInaute
Salut à toi,

J'ai bien aimé ton petit challenge et je pense qu'avec cette requête tu arriveras à avoir ce que tu veux :
Code:
SELECT R2.*,
       (CASE
           WHEN R2.Num < R1.Num THEN (SELECT MAX(Num)*2 FROM `test_requetes`) - R2.Num
           ELSE R2.Num
        END) AS Trie
FROM `test_requetes` R1
INNER JOIN `test_requetes` R2
ON R2.Marque = R1.Marque AND R2.Modele = R1.Modele AND R2.Moteur = R1.Moteur AND R2.Num <> R1.Num
WHERE R1.Num = :TON_ID
ORDER BY Trie
LIMIT 5;

Remplace TON_ID par le n° de produit (le 3 ou le 15 dans ton exemple) et test_requetes par le nom de ta table.

Bonne journée :)
 
WRInaute passionné
Merci pour vos réponses.

J'ai testé ta requête Hayabuzha et elle fonctionne parfaitement bien : bravo, chapeau bas, tu es un vrai crack de mysql ;) il fallait quand même la pondre cette requête.

Pour ta première réponse sur le forum c'est une très belle performance : tu remportes donc ce challenge :)

Marie-Aude t'as mis un pouce, je vais faire de même.
 
WRInaute passionné
Ouep.
Allez un bémol : côté performances, ça fait des sous-requêtes, moi avec mon mutualisé tout pourri je privilégie toujours de faire le moins de requêtes possibles et de traiter ensuite en PHP, ici ce serait une seule requête sur Marque & Modele.
 
Nouveau WRInaute
Ouep.
Allez un bémol : côté performances, ça fait des sous-requêtes, moi avec mon mutualisé tout pourri je privilégie toujours de faire le moins de requêtes possibles et de traiter ensuite en PHP, ici ce serait une seule requête sur Marque & Modele.

Oui en effet c'est une solution, mais la problématique de l'auteur était de réaliser son problème avec seulement une requête.

Cependant je serai curieux de voir si ta solution avec une traitement PHP serait malgré tout plus performante dans le cas où il y aurait des milliers voir des centaines de milliers d'enregistrements ?
Il faut savoir que le MySQL est très rapide et dans mon cas renverrait toujours 5 résultats en PHP. De plus ma sous requête qui fait le MAX n’alourdit pas forcément le processus.
Seul un benchmark pourrait nous le dire ;)
 
Discussions similaires
Haut