Получить поля из таблицы, которая имеет такое же отношение к другой таблице - PullRequest
1 голос
/ 16 марта 2009

Я постараюсь объяснить свой случай как можно лучше. Я делаю сайт, где вы можете найти темы, просматривая их теги. Ничего странного там нет. У меня есть время на некоторые вопросы. Они могут быть легкими для вас, мой разум довольно испорчен, выполняя много работы: P.

У меня есть таблицы "топики" и "теги". Они объединяются с использованием таблицы tags_topics, которая содержит topic_id и tag_id. Когда пользователь хочет найти тему, он может сначала выбрать один тег для фильтрации, а затем добавить другой в фильтр. Затем я делаю запрос для получения всех тем, которые имеют оба выбранных тегов. У них также могут быть другие теги, но они ДОЛЖНЫ иметь эти теги, выбранные для фильтрации. Количество тегов для фильтрации отличается, но у нас всегда есть список выбранных пользователем тегов для фильтрации. На это в основном ответили Фильтрация из таблицы соединений , и я выбрал решение для нескольких соединений.

Теперь мне нужно выбрать теги, по которым пользователь может фильтровать. Поэтому, если у нас уже есть определенный фильтр из 2 тегов, мне нужно выбрать все теги, кроме тех, которые в фильтре, связанном с темами, которые включают все теги в фильтре. Это может показаться странным, поэтому я приведу практический пример: P

Допустим, у нас есть три темы: теннис, спортзал и гольф.

  • теннис имеет теги: спорт, мяч, корт и ракетка
  • тренажерный зал имеет теги: спорт, тренировки и мышцы
  • Гольф имеет теги: спорт, мяч, клюшка и снаружи

    1. Пользователь выбирает тег спорт, поэтому мы показываем все три вида тенниса, тренажерный зал и гольф, а также показываем мяч, корт, ракетку, тренировки, мышцы, клюшку и внешний вид в качестве других возможных фильтров.
    2. Пользователь теперь добавляет мяч в фильтр. Фильтр теперь спорт и мяч, поэтому мы показываем темы тенниса и гольфа, с кортом, ракеткой, клюшкой и снаружи в качестве дополнительных возможных фильтров.
    3. Пользователь теперь добавляет к фильтру корт, поэтому мы показываем теннис и ракетку в качестве дополнительного возможного фильтра.

Надеюсь, у меня есть смысл. Кстати, я использую MySQL.

Ответы [ 4 ]

0 голосов
/ 16 марта 2009

Общее решение от макушки головы, но склонны к опечаткам:

  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

Вам просто нужно запросить представление related_tags.

Интересная задача, кстати.

0 голосов
/ 16 марта 2009
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 голосов
/ 16 марта 2009
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 )

Должен дать вам список тем, в которых есть все теги для selected_topic.

0 голосов
/ 16 марта 2009
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;

Приведенный выше запрос получит все topic_ids, которые имеют все три tag_id 1, 2 и 3. Затем используйте это как подзапрос:

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
       )

Я думаю, это то, что вы ищете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...