Formulation d'une requete un peu trop complexe pour moi ...

Eléphant du PHP | 91 Messages

28 août 2007, 16:37

Hello,

J'ai deux tables (mysql) l'une contenant divers infos (prix, id ... ) sur mes produits l'autre contenant les informations techniques. Parce que le label de ces informations varient d'un produit à l'autre, il y a un champ pour le label et un champ pour la valeur de l'information.

Table produit :

Code : Tout sélectionner

CREATE TABLE produit ( products_id int NOT NULL, products_price int, PRIMARY KEY (products_id) );
Table informations_produit :

Code : Tout sélectionner

CREATE TABLE informations_produit ( products_id int NOT NULL, products_fields_label int NOT NULL, products_fields_value varchar(64), PRIMARY KEY (products_id,products_fields_id) );
Mon but est de faire une requête qui n'afficherait que les produits dont les champs d'informations prendraient certaines valeurs.

Par exemple, les produits pour lesquels il y aurait, dans la table informations_produit, un label pays avec valeur France.

Ce qui donne cette requête :

Code : Tout sélectionner

SELECT p.products_id,p.products_price FROM produits p LEFT JOIN informations_produit ip on p.products_id = ip.products_id WHERE ip.products_fields_label = 'Pays' and ip.products_fields_value = 'France'
Seulement ce n'est possible de cette façon seulement si je n'ai qu'un seul critère de selection. Si jamais je recherche les produits pour lesquels il y aurait un label 'pays' avec valeur 'France' ET un label 'ville' avec valeur 'Toulouse', cette méthode ne marchera plus.


Merci de l'aide ;)


EDIT --------
Bon a priori il faut que je passe par une sous-requête du genre :

Code : Tout sélectionner

SELECT COUNT( * ) FROM informations_produit ip WHERE ip.products_id = ' ??? ' AND ((ip.products_fields_value = 'France' AND ip.products_fields_label = 'Pays) OR (ip.products_fields_value = 'Toulouse' AND ip.products_fields_label = 'ville'))
Seulement je ne sais pas trop comment imbriquer tout ça :?

Administrateur PHPfrance
Administrateur PHPfrance | 3088 Messages

28 août 2007, 21:18

D'abord, merci pour avoir correctement formatté ton message. Tellement de gens ignorent ce qui est écrit en rouge quand on poste un sujet que je commençais à désespérer :roll:
les produits pour lesquels il y aurait, dans la table informations_produit, un label pays avec valeur France
Si tu ne veux que les produits qui possèdent un label 'France', ce n'est pas un LEFT JOIN qu'il te faut utiliser mais un simple JOIN (synonyme d'INNER JOIN). Donc la requête devrait ressembler à

Code : Tout sélectionner

SELECT p.products_id,p.products_price FROM produits p JOIN informations_produit ip ON ip.products_id = p.products_id WHERE ip.products_fields_label = 'Pays' AND ip.products_fields_value = 'France'
Comme les valeurs de products_fields_label et products_fields_value sont des conditions de jointure j'aurais tendance à le mettre dans la jointure directement

Code : Tout sélectionner

SELECT p.products_id,p.products_price FROM produits p JOIN informations_produit ip ON ip.products_id = p.products_id AND ip.products_fields_label = 'Pays' AND ip.products_fields_value = 'France'
(désolé pour le formattage si t'es pas habitué :))

Ensuite, si tu veux ajouter d'autres critères, tu peux simplement ajouter d'autres jointures. "ipp" pour les pays, "ipv" pour les villes, par exemple

Code : Tout sélectionner

SELECT p.products_id,p.products_price FROM produits p JOIN informations_produit ipp ON ipp.products_id = p.products_id AND ipp.products_fields_label = 'Pays' AND ipp.products_fields_value = 'France' JOIN informations_produit ipv ON ipv.products_id = p.products_id AND ipv.products_fields_label = 'Ville' AND ipv.products_fields_value = 'Toulouse'
...qui devrait retourner ce que tu recherches.

Par curiosité, est-ce que tu pourrais me copier/coller un EXPLAIN de la requête stp ? Selon la taille de ta base de données et la répartition des enregistrements tu devrais peut-être mettre un index sur (ipv.products_fields_label,ipv.products_fields_value) parce que c'est par là que va commencer MySQL pour chercher les enregistrements.

Eléphant du PHP | 91 Messages

28 août 2007, 23:57

Merci, on peut difficilement faire plus clair :wink:

J'avais fini par réussir avec une sous-requête mais avec plus de 350 produits dans ma table et pour chacun à peu près 10 champs d'informations, mieux vaut sans doute éviter les requêtes trop gourmandes.

Désolé pour le EXPLAIN mais ma requête est crée dynamiquement et donc bourrée de php, pas trop le temps (bon surtout l'envie :wink: ) d'en réécrire une à la main, d'autant plus que les réelles tables sont bien moins simples que celles que j'ai donné en exemple ici.

Autrement, si ça peut te donner une idée, une fois que j'aurais rentré tout mes produits, il y aura 350 à 400 t-uples dans la table produits et donc 3500 à 4000 t-uples dans la table informations_produit.

ViPHP
ViPHP | 1380 Messages

29 août 2007, 08:41

Désolé pour le EXPLAIN mais ma requête est crée dynamiquement et donc bourrée de php, pas trop le temps (bon surtout l'envie :wink: ) d'en réécrire une à la main, d'autant plus que les réelles tables sont bien moins simples que celles que j'ai donné en exemple ici.
Tu sais, il suffit d'insérer un echo de ta requête et de faire un copier coller avec l'EXPLAIN. Ça te prendra moins de temps qu'il a fallu à Hubert Roksor pour te donner ces précieuses indications.

Surtout que ça en vaut la peine, EXPLAIN est une instruction très puissante que va t'indiquer comment MySQL exécute la requête et utilise les index éventuels.
http://dev.mysql.com/doc/refman/5.0/fr/explain.html

[private_joke]
désolé pour le formattage si t'es pas habitué
Hubert R. l'homme aux soft-tab à 30 ! :wink:

[/private_joke]
ripat

Invité
Invité n'ayant pas de compte PHPfrance

29 août 2007, 10:03

Tu sais, il suffit d'insérer un echo de ta requête et de faire un copier coller avec l'EXPLAIN. Ça te prendra moins de temps qu'il a fallu à Hubert Roksor pour te donner ces précieuses indications.
C'est pas faux ;)

Image

Enfin reste le problème que pour le moment ma base de donnée n'est pas remplie, je ne le ferais qu'au dernier moment, une fois l'ensemble de mon e-commerce codé. Donc la colonne rows n'est pas vraiment significative ici, puisque il y a seulement une 10aine de produits test.

Du coup, je ne sais pas si ça apporte beaucoup d'info ?

Eléphant du PHP | 91 Messages

29 août 2007, 10:31

J'ai tout bon moi ... je poste en invité et je laisse trainer ma souris sur le screenshot. Faut que j'arrête la coke le matin.

Voila un screenshot propre.
Image