Vous n'êtes pas identifié(e).
Bonjour,
Pour ceux qui suivraient mon évolution via ce forum, je suis toujours sur mon projet de site de cuisine. Il avance bien, merci. Un de ces jours je mettrai le lien pour que vous puissiez venir rire...
Bref, là je travaille sur une fonction de recherche de recettes par ingrédients.
Ce n'est pas pertinent dans mon principal souci, mais sur le principe, ça utilise AJAX et des checkbox divisées en deux catégories : ce que je veux, et ce que je ne veux pas.
Je teste actuellement la forme que doit prendre la requête directement sur MySQL.
Quand il y a un seul ingrédient à chercher, ceci marche très bien :
Explications :
3 tables concernées : recettes, recettes_ingredients, et ingredients. La table recettes_ingredients comporte notamment un champ ingredient_id et un champ remplacant, comportant tous les deux des ID d'ingrédients (id différents). Il me parait nécessaire que l'on puisse obtenir un résultat "du moment que l'ingrédient est soit principal, soit remplaçant".
Il me retourne bien la liste de toutes les recettes qui comportent de la farine.
Mais quand je veux ajouter un deuxième ingrédient, par exemple le sel, il ne m'affiche aucun résultat alors qu'il devrait y en avoir 3. J'utilise pour ça "WHERE ingredient_nom = 'farine' AND ingredient_nom = 'sel'" et j'espérais pouvoir ensuite ajouter autant de "AND ingredient_nom = 'machin'" tant que l'utilisateur coche des checkbox. Il y a donc forcément quelque chose que je fais mal dans cette condition, mais je n'arrive pas à mettre le doigt dessus. Auriez-vous l'amabilité de m'indiquer où est ma faute ?
Merci !
Hors ligne
Bonjour
"WHERE ingredient_nom = 'farine' AND ingredient_nom = 'sel'"
1) Sur le principe une requête ne peut te retourner pour le même champ des enregistrements pour deux valeurs différentes. Par contre elle peut te retourner des résultats avec nom='farine' OR nom ='sel'.
2) Pour utiliser AND il faut le faire à chaque fois pour une table différente, en utilisant ce que notre ami MK appele une table en auto equijointure.
Mais faut-il encore que ta table recettes_ingrédients soit construite comme une table de jonction pour pouvoir faire ce que tu cherches. En effet une recette étant composée de plusieurs ingrédients, il faut que chaque ingrédient d'une recette constitue un enregistrement de ta table recettes_ingredients.
En résumé :
TABLE recettes
- clé primaire : id INT unsigned not null auto_increment
TABLE ingrédients
- clé primaine : id INT unsigned not null auto_increment
TABLE recettes_ingrédients
- clé primaire : recette_id INT unsigned not null et ingredient_id INT unsigned not null.
De là tu auras bien de mémorisé dans recettes_ingredients l'ensemble des ingrédients pour chaque recette, et tu n'auras pas besoin d'auto equijointure dans ta requête .
++
Dernière modification par Jc (04-06-2011 15:34:33)
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Ah j'oubliais...
Si tu veux enregistrer pour une même recette des ingrédients de remplacement, du style mettre de la Maïzena à la place de la farine, je te conseille pour faire ça proprement de faire deux recettes différentes, l'une appelée 'recette classique' et l'autre 'recette allégée' par exemple.
Dernière modification par Jc (04-06-2011 15:39:45)
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Merci d'avoir répondu.
En l'état, je crois que mes trois tables ont bien la structure que tu me décris. Autant à mes débuts mes tables étaient chaotiques et mal pensées, autant grâce notamment à M "maiiiitre" K je pensais avoir réussi à optimiser toute cette pagaille...Je suis passé de une table à 125 champs (véridique ^^) à 6 tables puis enfin 3 tables...La table recettes_ingredients ressemble à ça (sans les noms d'ingrédients entre parenthèses, bien sûr) :
recette_id ingredient_id quantite unite remplacant facultatif
80 28(sel) bla bla bla bla
80 31(farine) bla bla bla bla
81 28(sel) bla bla bla bla
81 31(farine) bla bla bla bla
82 28(sel) bla bla bla bla
Du coup, comment dois-je formuler ma requête pour que ça marche si je ne peux pas faire de AND au sein de la même table ? J'avoue ne pas comprendre.
Hors ligne
Re,
si tu fais
ta requête te retournera l'ensemble des recettes qui contiennent soit de la farine (et pas de sel), soit du sel (et pas de farine), soit les recettes qui contiennent les deux.
Ce qu'il te faut c'est faire une recherche par recette. Il faut donc faire un regroupement des enregistrements. Tu pourrais faire par exemple :
++
EDIT: Les problèmes de AND, OR, NOT AND, NOT OR,..., sont des problèmes de logique appliquée, où il faut bien comprendre les notions de AND inclusif ou exclusif ainsi que de OR inclusif ou exclusif, et dans chacun des cas que je viens de citer la signification de leur contraire (NOT).
Dernière modification par Jc (04-06-2011 17:08:10)
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Merci ! Les notions de GROUP BY et HAVING me semblaient nébuleuses, ça va être l'occasion de les tester de près !
Hors ligne
Bonsoir,
Profites-en aussi pour tester de près les AND et les OR dans tes requêtes
++
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Oui je sens que je repasserai par là quand il s'agira de faire des "cet ingrédient, celui-ci aussi, mais pas celui-là"...
Merci, en tout cas. Après les premiers tests, ta recommandation semble marcher parfaitement.
Hors ligne
Bonjour,
J'ai réussi à faire la partie positive (AVEC ces ingrédients) grâce aux conseils donnés ci-dessus, et je bûche sur la partie négative (SANS ces ingrédients) avant d'entamer la partie utilisant les deux. Et je lutte et m'interroge.
Concernant la partie négative, ne faut-il pas sélectionner toutes les recettes qui ont l'un de tous les autres ingrédients via un "simple" (ingredient_nom = 'truc' OR ingredient_nom = 'machin'...etc) comprenant tous les ingrédients sauf ceux sélectionnés par l'utilisateur ? Ca me semble être toutefois très long et bancal comme principe et si c'est la solution, je n'ose envisager celle pour la recherche utilisant les AVEC et les SANS... Comment faire autrement ? Je pensais naïvement qu'une simple négation par != dans la requête positive marcherait mais les résultats sont incohérents.
Merci pour vos avis éclairés
Dernière modification par Mendoza (07-06-2011 10:13:48)
Hors ligne
Bonjour,
Pour te donner un exemple si tu veux faire une requête pour sélectionner les recettes qui n'utilisent ni de sel ni de farine, il faut que tu fasses :
++
Dernière modification par Jc (07-06-2011 20:48:49)
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Argh je suis pourtant sûr d'avoir testé cette possibilité... Je vais recommencer, j'ai dû me planter ailleurs. Merci. Encore.
Hors ligne
Ah la joie des AND, NAND, OR, NOR, XOR !
Gloire à qui n'ayant pas d'idéal sacro-saint,
Se borne à ne pas trop emmerder ses voisins. G. Brassens Don Juan 1976.
Avĉjo MoKo kantas
La chaîne YouTube MoKo Papy
Hors ligne
Doit y avoir un truc en plus...Quand je fais "SELECT recette_id FROM recettes_ingredients WHERE (ingredient_id <> '28' AND ingredient_id <> '31') GROUP BY recette_id" les résultats ne sont pas cohérents, je ne devrais pas avoir les crêpes là-dedans (entre autres erreurs)...Grmbll.
Hors ligne
pk le group by ?????????????
a++
Hors ligne
bonjour,
@pierrot : Ce qui nous interesse c'est la liste des recettes_id qui ne contiennent pas ces ingrédients. Or les doublons sur recette_id ne nous interessent pas non plus, d'où le GROUP BY. (De tout de manière tu n'a plus le droit de poster sur ce forum tant que tu n'as pas mis ta requête simplifiée à mort dans mon post que tu devais déjà mettre hier matin )
@mendoza: Pourtant ils devraient l'être. Es-tu certain d'avoir bien défini l'ensemble des ingrédients par recette? Car si tu as ingredient_id=28 et ingredient_id=31 de définis pour la recette_id des crêpes, elle n'apparaîtra pas dans les résultats de cette requête.
Je te rappelle une chose : ingredient_id<>28 AND ingredient_id<>31 te listera l'ensemble des recettes qui ne contiennent pas à du Sel OU de la Farine OU les deux. C'est à dire que si une recette contient du sel et pas de farine elle ne sera pas listée au même titre qu'une recette qui contient les deux.
Si tu souhaites que ta requête te liste les recettes qui contiennent du sel OU qui contiennent de la farine uniquement (c'est à dire qui ne contiennet pas les deux à fois) il faut écrire
Dernière modification par Jc (08-06-2011 07:34:04)
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Bonjour,
Juste une petite remarque sur mon post précédent. Ceci montre bien qu'il est souvent plus avantageux de travailler sur les enregistrement recherchés (par inclusion plutôt que par exclusion), car cela permet de pouvoir y appliquer des filtres supplémentaires. Mais bon parfois on ne peut pas toujours faire ce que l'on souhaite.
++
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Bon ça fait un moment que je m'énerve dessus. Je viens de faire une base de tests avec des nombres au pif pour les recettes, avec des ingrédients au pif. Et quand je fais la requête, j'ai des résultats cohérents. Mfff. Quelqu'un saurait pourquoi sur une table de tests faite en 3 secondes ça marcherait et pas sur la vraie ? Vous voyez une raison possible ?
Hors ligne
Doit-on invoquer la théorie du bordel ambiant de Roland Moreno ?
Gloire à qui n'ayant pas d'idéal sacro-saint,
Se borne à ne pas trop emmerder ses voisins. G. Brassens Don Juan 1976.
Avĉjo MoKo kantas
La chaîne YouTube MoKo Papy
Hors ligne
En fait, quelque soit la valeur de l'ingredient_id et quelque soit leur nombre, les résultats restent les mêmes. Strictement. Que je cherche de la farine, du poivre ou quoique ce soit d'autre, les mêmes : c'est à dire toutes les recettes qui ont des ingrédients (oui dans la base j'en ai qui ont juste servies à tester les différents champs, donc qui n'ont pas forcément d'ingrédient).
Hors ligne
Il va falloir te résoudre à mettre ton script en entier sur le Wall, et nous donner le lien vers celui-ci ici.
J'ai le sentiment que ce n'est pas forcément la requête qui est en cause mais la logique de son appel.
Gloire à qui n'ayant pas d'idéal sacro-saint,
Se borne à ne pas trop emmerder ses voisins. G. Brassens Don Juan 1976.
Avĉjo MoKo kantas
La chaîne YouTube MoKo Papy
Hors ligne
Ce qu'il y a, c'est que cette même bdd renvoie les bonnes données quand je fais la première requête AVEC.
Le $nom contient une ligne facultative avec un AND recette_nom LIKE '%$rechRecette%' si l'utilisateur tape un nom dans la case prévue pour.
Le $classe contient un paramètre permettant de filtrer les recherches par classe de recettes (entrées/plats/desserts/apéros : "AND recette_classe = 'entree'" par ex.).
le $valeurs est un implode des valeurs cochées par l'utilisateur séparées par des " OR ingredient_nom = ".
Le $nb contient le nombre de valeurs cochées.
Là, je n'ai pas constaté la moindre erreur de cohérence. Si le problème de la recherche SANS venait de la table, est-ce que ça pourrait marcher aussi bien pour la partie AVEC ?
Je précise que quand je fais la recherche AVEC simplifiée (juste un SELECT recette_id FROM recettes_ingredients WHERE ingredient_nom = '28' OR ingredient_nom = '31' HAVING COUNT etc.) j'obtiens les mêmes résultats.
Pour la partie SANS, quand je fais une requête plus ardue inspirée de celle ci-dessus (donc avec les noms des ingrédients et des recettes pour plus de lisibilité) sans GROUP BY pour tâcher de comprendre ce qu'il fait, en ne disant seulement que je ne veux pas de farine, il est tout fier de me retourner par exemple toutes les lignes d'ingrédients des crêpes SAUF celle qui concerne effectivement la farine. Donc il comprend vaguement ce que je veux, c'est juste qu'il s'en fout. Je pense qu'il rit en me voyant rager. Le pire c'est qu'il encadre les ingrédients histoire de bien me montrer qu'il sait. Il m'en veut pour toutes les approximations que je lui ai fait subir. Hum pardon, je pète les plombs.
Donc je suis ouvert à l'utilisation du Wall. Quelles parties du code faut-il que j'y mette ?
Hors ligne
Donc je suis ouvert à l'utilisation du Wall. Quelles parties du code faut-il que j'y mette ?
Le formulaire et son traitement.
Gloire à qui n'ayant pas d'idéal sacro-saint,
Se borne à ne pas trop emmerder ses voisins. G. Brassens Don Juan 1976.
Avĉjo MoKo kantas
La chaîne YouTube MoKo Papy
Hors ligne
Pardon pour la nouvelle question stupide, mais je n'ai pas encore organisé le traitement négatif du formulaire, j'attendais de savoir formuler correctement la requête, uniquement via l'interface de mysql. Tu veux quand même que je mette la partie positive ? Ou le plus simple est peut-être encore que je vous donne l'adresse de la page du site ?
Hors ligne
Bonjour,
Je viens de relire attentivement ta requête de production, et il y a tout de même des différences à prendre en compte si tu veux obtenir les résultats que tu es censé obtenir.
1) il faut que tu t'assures que $nom et $classe soient respectivement égal à " " si ils ne sont pas utilisés.
2) Il faut que tes recettes soient validées pour être pris en compte.
3) Vu que tu appliques un filtre de recherche par nom de recette supplémentaire (qui lui aussi doit être égal à " " si ce n'est pas le cas) tu peux avoir un souci de jointure du fait qu'elles ne soient pas déclarées explicitrement (LEFT JOIN - RIGHT JOIN - INNER JOIN) et qui n'ont pas le même effet d'autant que la table sur lequel tu appliques ce filtre n'est pas la même que ta table de jonction (qui est en LEFT par rapport aux autres). Normalement donc tu devrais faire un
Dans cette ligne j'ai omis le OR du remplaçant qui est à étudier de près avant de l'inclure.
En effet il serait plus judicieux pour faire les choses proprement de faire un LEFT JOIN supplémentaire pour le remplacant en auto equijointure et d'être certain du resultat obtenu.
Mais je pense que le mieux pour faire ce que tu recherches reste tout de même de l'inclure dans ta clause WHERE.
++
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne
Re bonjour,
Un petit oubli de ma part.
Concernant,
Je ne suis pas certain que cela soit toujours pertinent selon ce que vous cherchez à faire, d'autant que le nombre de critères d'ingredients recherché peut être >3 vu l'implémentation.
Dans ce contexte seul deux valeurs pour nb sont possibles pour préserver la pertinence du filtre.
1) nb=1 : Au moins un ingrédient parmis la liste est contenu dans la recette.
2) nb=count(recette_id) : UNIQUEMENT tous les ingrédients doivent être présent dans la recette recherchée.
En effet des valeurs intermédiaires signifieraient par ex que 2 ou 3 ingrédients sur 5 doivent être présents. Mais lesquels seront retenus par la requête? Même si on peut répondre à la question en analysant le fonctionnement de l'interpréteur de MySQL, la pertinence du nombre de critères d'ingrédients saisis dans la requête ne serait plus.
Si il y a un truc que tu n'a pas compris, n'hésite pas à demander.
++
Dernière modification par Jc (09-06-2011 17:12:57)
POO PHP+Ajax en MVC avec PDO et Bases de données épaisses : What else?
Hors ligne