2009-03-16 6 views
1

Je vais essayer d'expliquer mon cas aussi bien que possible. Je crée un site Web où vous pouvez trouver des sujets en parcourant leurs tags. Rien d'étrange là-bas. J'ai du mal avec certaines des questions. Ils pourraient être facile pour vous, mon esprit est assez foiré de faire beaucoup de travail: P.Récupérer des champs d'une table qui a la même relation avec une autre table

J'ai les tables "topics" et "tags". Ils sont joints en utilisant la table tags_topics qui contient topic_id et tag_id. Lorsque l'utilisateur souhaite trouver un sujet, il peut d'abord sélectionner une étiquette à filtrer, puis en ajouter une autre au filtre. Ensuite, je fais une requête pour aller chercher tous les sujets qui ont les deux balises sélectionnées. Ils peuvent également avoir d'autres balises, mais ils DOIVENT avoir ces balises choisies pour filtrer. La quantité de tags à filtrer diffère, mais nous avons toujours une liste de tags sélectionnés par l'utilisateur pour filtrer. Cela a été la plupart du temps répondu en Filtering from join-table et je suis allé pour la solution de jointures multiples.

Maintenant, j'ai besoin de récupérer les balises que l'utilisateur peut filtrer. Donc, si nous avons déjà un filtre défini de 2 balises, j'ai besoin de récupérer toutes les balises sauf celles du filtre associé aux sujets qui inclut toutes les balises du filtre. Cela peut sembler bizarre, donc je vais donner un exemple pratique: P

Disons que nous avons trois sujets: tennis, gym et golf.

  • tennis a tags: sport, basket, terrain et raquette
  • gymnase a tags: le sport, la formation et les muscles
  • golf a tags: sport, boule, bâton et à l'extérieur

    1. L'utilisateur sélectionne le sport de tag, ainsi nous montrons tous les trois tennis, gymnase et golf, et nous montrons le ballon, la cour, la raquette, l'entraînement, les muscles, le bâton et dehors comme d'autres filtres possibles. L'utilisateur ajoute maintenant une bille au filtre. Le filtre est maintenant sport et balle, donc nous montrons les sujets tennis et golf, avec le court, la raquette, le bâton et l'extérieur comme filtres supplémentaires possibles. L'utilisateur ajoute maintenant le court au filtre, ainsi nous montrons le tennis et la raquette comme un filtre supplémentaire possible.

J'espère que je fais un certain sens. Au fait, j'utilise MySQL.

+0

On ne sait pas ce qui rend les balises 1, 2 et 3 spéciales d'une manière que le «tas d'autres balises» ne le fait pas. Pourquoi sont-ils nécessaires alors que les autres ne le sont pas, et comment le saurions-nous? Est-ce une liste prédéfinie de tags que nous pouvons simplement supposer? – chaos

+0

Vous voudrez peut-être donner une structure de tableau et mieux expliquer la question. Je pense que j'ai eu ce que tu veux mais il a fallu le lire 5 fois avant de comprendre. – achinda99

+0

Exact dupliquer de http://stackoverflow.com/questions/648308/filtering-from-join-table –

Répondre

0
SELECT DISTINCT `tags`.`tag` 
FROM `tags` 
LEFT JOIN `tags_topics` ON `tags`.`id` = `tags_topics`.`tag_id` 
LEFT JOIN `topics` ON `tags_topics`.`topic_id` = `topics`.`id` 
LEFT JOIN `tags_topics` AS `tt1` ON `tt1`.`topic_id` = `topics`.`id` 
LEFT JOIN `tags` AS `t1` ON `t1`.`id` = `tt1`.`tag_id` 
LEFT JOIN `tags_topics` AS `tt2` ON `tt2`.`topic_id` = `topics`.`id` 
LEFT JOIN `tags` AS `t2` ON `t2`.`id` = `tt2`.`tag_id` 
LEFT JOIN `tags_topics` AS `tt3` ON `tt3`.`topic_id` = `topics`.`id` 
LEFT JOIN `tags` AS `t3` ON `t3`.`id` = `tt3`.`tag_id` 
WHERE `t1`.`tag` = 'tag1' 
AND `t2`.`tag` = 'tag2' 
AND `t3`.`tag` = 'tag3' 
AND `tags`.`tag` NOT IN ('tag1', 'tag2', 'tag3') 
+0

Merci, ressemble à une solution "simple". Se sent mieux optimisé, performance sage, que de faire des sous-requêtes. – finpingvin

+0

Oui, mais c'est limité à 3 tags. –

+0

Mais la requête peut être construite dynamiquement dans le code de l'application – finpingvin

0
SELECT topic_id 
FROM  topic_tag 
WHERE tag_id = 1 
     OR tag_id = 2 
     OR tag_id = 3 
GROUP BY topic_id 
HAVING COUNT(topic_id) = 3; 

La requête ci-dessus obtiendra tous les topic_ids qui ont tous les trois tag_ids de 1, 2 et 3. Ensuite, utiliser comme sous-requête:

SELECT tag_name 
FROM tag 
     INNER JOIN topic_tag 
ON  tag.tag_id = topic_tag.tag_id 
WHERE topic_id IN 
        (SELECT topic_id 
        FROM  topic_tag 
        WHERE tag_id = 1 
          OR tag_id = 2 
          OR tag_id = 3 
        GROUP BY topic_id 
        HAVING COUNT(topic_id) = 3 
        ) 
    AND 
     (
       tag.tag_id <> 1 
      OR tag.tag_id <> 2 
      OR tag.tag_id <> 3 
     ) 

Je pense que c'est ce que vous recherchez.

+0

Au lieu d'utiliser IN, vous pouvez faire une jointure interne, mais vous devez ensuite renommer certaines colonnes et me sentir paresseux. – achinda99

0
Select a.topic_id 
    from join_table a 
where exists(select * 
       from join_table b 
       where a.tag_id = b.tag_id 
        and b.topic_id = selected_topic) 
group by a.topic_id 
having count(*) = (select count(*) 
         from join_table c 
         where c.topic_id = selected_topic) 

devrait vous donner une liste de sujets qui ont toutes les balises pour selected_topic.

0

solution générique du haut de ma tête, mais enclin à avoir des fautes de frappe:

CREATE VIEW shared_tags_count AS 
    SELECT topic_to_tag1.topic_id AS topic_id1, topic_to_tag2.topic_id AS topic_id2, COUNT(*) as number 
    FROM topic_to_tag as topic_to_tag1 
     JOIN topic_to_tag as topic_to_tag2 
     ON topic_to_tag1.topic_id <> topic_to_tag2.topic_id 
      AND topic_to_tag1.tag_id = topic_to_tag2.tag_id 
GROUP BY topic_to_tag1.topic_id, topic_to_tag2.topic_id; 

    CREATE VIEW tags_count AS 
    SELECT topic_id, COUNT(*) as number 
    FROM topic_to_tag 
GROUP BY topic_id 

CREATE VIEW related_topics AS 
SELECT shared_tags_count.topic_id1, shared_tags_count.topic_id2 
    FROM shared_tags_count 
     JOIN tags_count 
     ON topic_id=topic_id1 
      AND shared_tags_counts.number = tags_count.number 

CREATE VIEW related_tags AS 
SELECT related_topics.topic_id1 as topic_id, topic_to_tag.tag_id 
    FROM related_topics 
     JOIN topic_to_tag 
     ON raleted_topics.tag_id2 = topic_to_tag.topic_id 

Il vous suffit d'interroger la vue related_tags.

Défi intéressant btw.

+0

Cela semble complexe: P – finpingvin

+0

principalement en raison de noms de table;) J'aime casser les problèmes en vues. Plus de code mais plus facile à gérer lorsque vous avez des modifications dans votre schéma. –

+0

Oui, je peux voir ça :) Je n'ai jamais utilisé de vues en fait, je pourrais avoir à regarder ça. – finpingvin

Questions connexes