IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage SQL Discussion :

Moteur de recherche par tags avec table relationelle


Sujet :

Langage SQL

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    240
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 240
    Points : 81
    Points
    81
    Par défaut Moteur de recherche par tags avec table relationelle
    Bonjour,

    Je dois résoudre un probleme qui me semble assez difficile

    Je dois créer une requete SQL pour un moteur de recherche par tags.
    J'ai 3 tables : article, tag, relation. la table relation est composé juste de article.id et tag.id.

    J'aimerais pouvoir rechercher les articles correspondent à plusieurs tags via l'id de ces tags.

    Par exemple un article numéro 1 est relié aux tags : chat et chien
    et un autre numéro 2 aux tags : chat et poisson.

    Si je recherche chat chien je ne dois trouver que l'article numéro 1 et non pas le 2 vu qu'il n'est associé qu'a chat et pas chien.

    Voici ma requete :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    SELECT DISTINCT
           f, articles.id, price,url
      FROM articles
           INNER JOIN relationships
             ON relationships.article_id = articles.id
           INNER JOIN tags
             ON tags.id = relationships.tag_id
     WHERE articles.st = 0
       AND relationships.tag_id IN (1191, 163)
     LIMIT 100
    1191 et 163 correspond aux ids des tags inclu dans ma recherche, cette requete marche mais retourne les articles qui ont pour tags 1191 OU 163 et j'aimerais qu'il ne retourne que les articles qui ont pour tags 1191 ET 163 ...

    Merci de votre aide

  2. #2
    Membre éprouvé Avatar de Oishiiii
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2009
    Messages
    508
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Août 2009
    Messages : 508
    Points : 1 104
    Points
    1 104
    Par défaut
    Bonsoir,

    Citation Envoyé par Overstone Voir le message
    Par exemple un article numéro 1 est relié aux tags : chat et chien
    et un autre numéro 2 aux tags : chat et poisson.

    Si je recherche chat chien je ne dois trouver que l'article numéro 1 et non pas le 2 vu qu'il n'est associé qu'a chat et pas chien.
    Il faut compter le nombre de tags trouvés grâce à la clause WHERE.
    J'utilise la clause HAVING.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SELECT DISTINCT articles.id, price,url
    FROM articles
      INNER JOIN relationships
        ON relationships.article_id = articles.id
    WHERE articles.st = 0
        AND relationships.tag_id IN (1191, 163)
    GROUP BY articles.id
    HAVING Count(*) = 2
    LIMIT 100
    Dans la partie "HAVING Count(*) = X", X correspond au nombre de tags recherchés.
    Je n'effectue pas de jointure sur la table tags, elle n'est pas utile ici je pense.

    A tester.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    240
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 240
    Points : 81
    Points
    81
    Par défaut
    Un grand merci ! Ça marche ! Donc si je comprend bien à chaque tags supplémentaire j'incrémente HAVING count(*) ?

    Sinon en effet la table tags n'a aucune utilité c'est un oubli lors de mes test.

    Merci beaucoup pour cette réponse rapide et clair !

  4. #4
    Membre éprouvé Avatar de Oishiiii
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2009
    Messages
    508
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Août 2009
    Messages : 508
    Points : 1 104
    Points
    1 104
    Par défaut
    Oui, si vous cherchez un article avec 5 tags, vous écrirez "HAVING Count(*) = 5".
    La requête retournera uniquement les articles ayants exactement 5 tags, les tags présent dans IN(..).

  5. #5
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Des erreurs dans la requête de Oishiiii :
    • Utiliser DISTINCT avec GROUP BY, c'est inutile et ça démontre une mauvaise compréhension des concepts (ou alors c'est un oubli de copier / coller ).
    • Il ne faut pas faire le HAVING sur le count(*), mais sur le nombre distincts d'éléments. Si vous avez deux fois le premier tag, le count(*) renvoie deux.
    • MySQL permet les agrégats avec des GROUP BY moisis, mais si vous voulez bien le faire il faut mettre tous les éléments du SELECT non agrégés.
    • Les alias de tables raccourcissent la requête et facilitent la relecture.


    Au final :
    Code sql : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
      SELECT art.id, art.price, art.url
        FROM articles as art
             INNER JOIN relationships as rls
               ON rls.article_id = art.id
       WHERE art.st = 0
         AND rls.tag_id IN (1191, 163)
    GROUP BY art.id, art.price, art.url
      HAVING count(distinct rls.tag_id) = 2;

  6. #6
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    240
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 240
    Points : 81
    Points
    81
    Par défaut
    Bonjour,

    Merci Waldar en effet cette requete marche beaucoup mieux que la précédente, cependant je suis obligé de faire un DISTINCT sur l'id car je me retrouve sinon avec une répétition de l'ensemble des articles de nombreuses fois, je ne sais pas si je peux résoudre ce probleme différament

  7. #7
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Comment ça, vous pouvez illustrer par l'exemple ?
    GROUP BY effectue déjà un DISTINCT.

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    240
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 240
    Points : 81
    Points
    81
    Par défaut
    Non c'est moi désolé, car en réalité quand il n'y a aucune recherche effectué ma requete devient :

    SELECT art.id, art.f, art.price, art.url FROM articles AS art INNER JOIN relationships AS rls ON rls.article_id = art.id WHERE art.st = 0

    Donc forcément je me retrouve avec plusieurs articles identiques, seulement est t'il correct de mettre un DISTINCT quoi qu'il arrive donc quand il n'y a pas de recherche et que ma requete n'a pas de GROUP BY et également dans le cas contraire ?

    Ou est il plus correct d'adapter la requete en fonction ?

  9. #9
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Il faut toujours adapter la requête en fonction du besoin, c'est fait pour ça le SQL !

    Quand on commence à faire des concessions et qu'on se dit c'est pas grave ça marche quand même, c'est à partir de ce moment-là qu'on devient un mauvais développeur...

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    240
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 240
    Points : 81
    Points
    81
    Par défaut
    Oui, c'est vrai aussi Merci beaucoup ! Je pense que je peux considerer ce post comme résolu

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. moteur de recherche par défaut firefox
    Par sympho dans le forum Firefox
    Réponses: 7
    Dernier message: 13/07/2009, 16h35
  2. Moteur de recherche multi critères avec filtre
    Par kina17 dans le forum SQL Procédural
    Réponses: 1
    Dernier message: 08/04/2008, 19h33
  3. Recherche par Tag
    Par Oberown dans le forum Algorithmes et structures de données
    Réponses: 1
    Dernier message: 28/08/2006, 17h30
  4. [Tableaux] Moteur de recherche par mot clés
    Par Nee dans le forum Langage
    Réponses: 4
    Dernier message: 20/01/2006, 11h30
  5. Moteur de recherche par date
    Par Prue dans le forum ASP
    Réponses: 17
    Dernier message: 27/08/2003, 16h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo