Précédent   Forum des professionnels en informatique > Bases de données > Langage SQL
Langage SQL Forum d'entraide sur le langage SQL et sur les questions liées à la conception de schéma (DDL). Cours SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 12/08/2011, 11h08   #1
Invité de passage
 
Homme
Webmaster
Inscription : août 2011
Messages : 9
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Webmaster
Secteur : Boutique - Magasin

Informations forums :
Inscription : août 2011
Messages : 9
Points : 0
Points : 0
Par défaut Recherche multiple de tags (MySQL)

Bonjour,

Sur mon site, j'ai un système de tags à cocher pour effectuer une recherche de produits sur mon site, présenté comme ceci :

+ Couleur + Taille + Style
*tag *tag *tag
*tag *tag *tag
*tag *tag *tag

(en colonnes / type de tags)

Je veux faire en sorte que le visiteur puisse, par exemple cliquer sur 2 couleurs et 1 style et avoir comme résultats les produits ayant une des deux couleurs ET le style coché. Si le visiteur choisit deux couleurs et deux styles, le résultat doit contenir les produits ayants au moins 1 couleur ET 1 style correspondant.

Après pas mal de recherches, je n'ai trouvé qu'une solution mais très peu valable (30sec / requête, trop long surtout pour une solution AJAX... )

Code :
1
2
3
4
5
6
SELECT   p.products_id
FROM products p
WHERE products_id IN
( SELECT ttp.products_id FROM tags_to_products ttp WHERE  tags_id = 581 OR tags_id = 567 ) AND
products_id IN
( SELECT ttp.products_id FROM tags_to_products ttp WHERE  tags_id = 291);
Avez-vous une meilleure solution à m'indiquer ? Merci !
holoduke est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/08/2011, 11h15   #2
Membre émérite
 
Homme Olivier Dehorter
Ingenieur de recherche - Ecologue
Inscription : juin 2003
Messages : 697
Détails du profil
Informations personnelles :
Nom : Homme Olivier Dehorter
Localisation : France

Informations professionnelles :
Activité : Ingenieur de recherche - Ecologue

Informations forums :
Inscription : juin 2003
Messages : 697
Points : 837
Points : 837
Pensez à utiliser la balise "CODE"

Pourquoi ne pas utiliser les jointures ?
Code :
1
2
3
4
SELECT P.Products_id
  FROM Products P
    INNER JOIN Tags_to_products Ttp ON Ttp.Products_id = P.Products_id
WHERE Ttp IN (581, 567, 291)
dehorter olivier est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/08/2011, 11h27   #3
Membre Expert
 
Inscription : janvier 2010
Messages : 1 084
Détails du profil
Informations personnelles :
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : janvier 2010
Messages : 1 084
Points : 1 573
Points : 1 573
Bonjour

@dehorter olivier : attention, cette requête renverra les produits qui valident UN critère parmi les trois, et non un critère sur la couleur ET le critère sur le style.
Il faudrait pour cela deux jointures (dans l'exemple donné), et en fait trois dans le cas général : joindre la table Tags_to_products pour chaque type de tag.

pour l'exemple donné, cela donnerait :
Code SQL :
1
2
3
4
5
6
7
8
9
 
SELECT P.Products_id
FROM Products P
INNER JOIN Tags_to_products couleur
    ON couleur.Products_id = P.Products_id
    AND couleur.tags_id IN(581,567)
INNER JOIN Tags_to_products style
    ON style.Products_id = P.Products_id
    AND style.tags_id IN(291)

Pour le cas plus général, cela dépend de la façon dont vous passez les paramètres a votre requête (construisez vous dynamiquement la requête ?)

Cependant, cela ne reste qu'une légère optimisation : remplacement de vos IN par des jointures. Et 30 secondes pour votre requête, cela me parait très long. Je suspecte un index manquant, certainement sur la colonne tags_id (qui pourrait inclure products_id pour être couvrant)

Enfin, je suppose que vous voulez par la suite récupérer d'autres informations que le product_id, sinon la table products me semble inutile dans votre requête
aieeeuuuuu est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 12/08/2011, 11h31   #4
Membre émérite
 
Homme Olivier Dehorter
Ingenieur de recherche - Ecologue
Inscription : juin 2003
Messages : 697
Détails du profil
Informations personnelles :
Nom : Homme Olivier Dehorter
Localisation : France

Informations professionnelles :
Activité : Ingenieur de recherche - Ecologue

Informations forums :
Inscription : juin 2003
Messages : 697
Points : 837
Points : 837
oups
dehorter olivier est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/08/2011, 14h42   #5
Invité de passage
 
Homme
Webmaster
Inscription : août 2011
Messages : 9
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Webmaster
Secteur : Boutique - Magasin

Informations forums :
Inscription : août 2011
Messages : 9
Points : 0
Points : 0
aieeeuuuuu je vais tester ta méthode ça me semble pas mal ! Je ne savais pas que l'on pouvais faire 2 INNER JOIN sur la même table. Merci !

dehorter olivier, merci mais ta méthode s'applique uniquement si on souhaite que tous les tags soient cherchés avec des OU entre eux, sans prendre en compte les colonnes.
holoduke est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 12/08/2011, 15h53   #6
Invité de passage
 
Homme
Webmaster
Inscription : août 2011
Messages : 9
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Webmaster
Secteur : Boutique - Magasin

Informations forums :
Inscription : août 2011
Messages : 9
Points : 0
Points : 0
aieeeuuuuu je confirme, ça marche très bien!
holoduke est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 13h47   #7
Invité de passage
 
Homme
Webmaster
Inscription : août 2011
Messages : 9
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Webmaster
Secteur : Boutique - Magasin

Informations forums :
Inscription : août 2011
Messages : 9
Points : 0
Points : 0
Par défaut Aide pour Requête sur tags

Bonjour à tous,

Je cherche à faire une requête MySQL permettant de chercher des produits par leurs tags, sur une base osCommerce trafiquée.
Deux tables sont concernées: products et tags_to_products (qui lie les tables products et tags par leurs id)

Pour être plus précis, j'ai plusieurs catégories de tags qui se présentent ainsi:

Couleur
| Rouge
| Jaune
| Bleu

Matière
| Fer
| Bois
| Acier

etc...


Chaque tags présentant une checkbox, l'utilisateur peu en choisir plusieurs de catégories différentes.
Mon problème: Si l'utilisateur choisit plusieurs tags dans des catégories différentes.
Mettons que l'utilisateur choisissent Rouge, Jaune et Acier.
J'aimerais que les résultats donnent les produits qui on soit la couleur Rouge, soit la couleur Jaune, soit Rouge et Jaune mais qui soient obligatoirement en Acier.
Pour résumé, mon but est que les produits obtenus aient au moins 1 tags de chaque catégories sélectionnées qui corresponde.

J'ai trouvé un moyen mais qui alourdi considérablement la requête, en faisant plusieurs INNER JOIN de la table tags_to_products, autant qu'il a de catégories de tags à trier.

Voilà, je ne sais pas si j'ai été assez clair sur mes intentions ou sur ma description, mais je pense que la nature du problème doit connue et sa résolution aussi. Si vous souhaitez plus d'informations n'hésitez pas...
holoduke est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 13h52   #8
Invité de passage
 
Homme
Webmaster
Inscription : août 2011
Messages : 9
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Webmaster
Secteur : Boutique - Magasin

Informations forums :
Inscription : août 2011
Messages : 9
Points : 0
Points : 0
Finalement j'ai à nouveau un problème, la requête est extrêmement lourde et fait fréquemment planter le serveur! Est-il possible de l'optimiser?
holoduke est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 13h55   #9
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 638
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 638
Points : 2 630
Points : 2 630
Bonjour,

Manque la structure des tables, la requete que vous effectuez, les indexs.
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 14h05   #10
Invité de passage
 
Homme
Webmaster
Inscription : août 2011
Messages : 9
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Webmaster
Secteur : Boutique - Magasin

Informations forums :
Inscription : août 2011
Messages : 9
Points : 0
Points : 0
Citation:
Envoyé par punkoff Voir le message
Bonjour,

Manque la structure des tables, la requete que vous effectuez, les indexs.
C'est mieux expliqué dans le lien que j'ai posté, merci d'avance.
holoduke est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 14h27   #11
Expert Confirmé
 
Homme
Inscription : mai 2002
Messages : 1 638
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 29
Localisation : France, Rhône (Rhône Alpes)

Informations forums :
Inscription : mai 2002
Messages : 1 638
Points : 2 630
Points : 2 630
non j'ai bien lu votre lien et aucune des 3 choses que je vous demande n'est fournit / explicité.

aujourd'hui vous utilisez une requete, on ne sait pas laquelle c'est (celle de aieeuuuuu ?) .
On ne connait pas la structure des tables.

vous vous plaignez de lenteur => on ne connait pas les indexs.
punkoff est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 14h56   #12
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 684
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 684
Points : 10 431
Points : 10 431
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Normalement votre couple (Products_id, Tags_Id) doit être une clef primaire de la table Tags_to_products et de facto être indexée.
Ça devrait répondre rapidement.

Ici j'aurai utilisé des existences plutôt que des jointures ou des IN :
Code :
1
2
3
4
5
6
7
8
9
10
SELECT Prd.Products_id
  FROM Products AS Prd
 WHERE EXISTS (SELECT NULL
                 FROM Tags_to_products AS Tp1
                WHERE Tp1.Products_id = Prd.Products_id
                  AND Tp1.tags_id IN (581,567))
   AND EXISTS (SELECT NULL
                 FROM Tags_to_products AS Tp2
                WHERE Tp2.Products_id = Prd.Products_id
                  AND Tp2.tags_id = 291)
Quelles sont les volumétries de vos tables ?
__________________
Email : http://scr.im/waldar
Waldar est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 16h12   #13
Invité de passage
 
Homme
Webmaster
Inscription : août 2011
Messages : 9
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Webmaster
Secteur : Boutique - Magasin

Informations forums :
Inscription : août 2011
Messages : 9
Points : 0
Points : 0
Waldar, je viens de tester cette solution mais là ça plante pour de bon.
La table products contient + ou - 10000 produits, la table tags_to_products + ou - 30000 entrées

La requête dans son état actuel dure 17 secondes.
holoduke est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 16h34   #14
Membre Expert
 
Inscription : août 2009
Messages : 779
Détails du profil
Informations forums :
Inscription : août 2009
Messages : 779
Points : 1 098
Points : 1 098
Avec les index naturels, ça devrait passer sans le moindre problème ... Les 17 secondes sont-elles sur la base, ou depuis le site ?

Car si les requêtes génèrent de très grosses listes de résultats, le problème n'est plus le temps de traitement de la requête, mais la mémoire occupée côté serveur par la liste des 10 000 produits + le temps de communication BDD - Serveur puis Serveur - Browser par Ajax.
D'ailleurs, est-il vraiment intéressant pour qui que ce soit d'avoir une liste de 10 000 produits affichés ?
Pouvez-vous essayer de rajouter une condition de limite du nombre de résultats et voir si ça améliore le temps sur le site ?

Dernier point : la requête mentionnée ne comporte que les id. Est-ce que par hasard derrière il y aurait une boucle qui irait, à partir de l'id, chercher les valeurs de chaque produit ? Auquel cas, il faudrait simplement requêter en une fois les valeurs souhaitées pour l'affichage.
Rei Ichido est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 16h46   #15
Invité de passage
 
Homme
Webmaster
Inscription : août 2011
Messages : 9
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Webmaster
Secteur : Boutique - Magasin

Informations forums :
Inscription : août 2011
Messages : 9
Points : 0
Points : 0
Les 17 secondes sont sur la base uniquement, c'est le slow error log qui me le donne.

La requête génère peu de résultat (0->200 admétons), les chiffres que j'ai donné correspondent aux nombre d'entrées sur les tables.
Du coup est-il toujours intéressant de limiter le nombre de valeurs à retourner?
holoduke est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 16h48   #16
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 684
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 684
Points : 10 431
Points : 10 431
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
Vous le faites tourner sur quelle machine votre MySQL ?
Parce que là c'est risible quand même les performances vue la volumétrie.

J'ai reproduis le cas sur Oracle.
100.000 produits, 2 millions de tag.

La requête dure 200 millisecondes.

Vous n'avez pas répondu sur les contraintes et index de vos tables.
__________________
Email : http://scr.im/waldar
Waldar est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 16h56   #17
Invité de passage
 
Homme
Webmaster
Inscription : août 2011
Messages : 9
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

Informations professionnelles :
Activité : Webmaster
Secteur : Boutique - Magasin

Informations forums :
Inscription : août 2011
Messages : 9
Points : 0
Points : 0
Alors en effet je viens de me rendre compte que la table tags_to_products n'a plus d'index ni de clé primaire

Je connais la sortie...

Si la requête pose toujours problème je reviendrais vers vous mais je ne pense pas...
holoduke est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2012, 16h58   #18
Modérateur
 
Homme Fabien
Ingénieur d'études en décisionnel
Inscription : septembre 2008
Messages : 5 684
Détails du profil
Informations personnelles :
Nom : Homme Fabien
Âge : 34
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Ingénieur d'études en décisionnel
Secteur : Arts - Culture

Informations forums :
Inscription : septembre 2008
Messages : 5 684
Points : 10 431
Points : 10 431
Envoyer un message via ICQ à Waldar Envoyer un message via Skype™ à Waldar
L'important c'est d'avoir résolu votre problème.
Dites-nous ce que ça donne !
__________________
Email : http://scr.im/waldar
Waldar est actuellement connecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 11h15.


 
 
 
 
Partenaires

Hébergement Web