Фильтрация из таблицы соединений

У меня возникли проблемы с хитрым SQL-запросом.

В моей базе данных MySQL есть темы таблиц, теги и теги_темы, чтобы присоединиться к ним. Я хочу получить темы, которые имеют одни и те же указанные теги. Например, допустим, у меня есть 3 тега с идентификаторами 1, 2 и 3, я хочу получить все темы, с которыми связаны теги 1, 2 и 3. Темы могут иметь другие теги, но должны иметь все указанные теги.

Помогите подумать плз xD

EDIT: найдено решение с использованием GROUP BY в этом вопросе: Извлечение только тех строк, которые соответствуют всем записям в объединенной таблице (SQL) Если у кого-то есть более элегантное решение, напишите :)


person finpingvin    schedule 15.03.2009    source источник


Ответы (2)


JOIN решение:

SELECT t.*
FROM topics t
 JOIN tags_topics t1 ON (t.id = t1.topicId AND t1.tagId = 1)
 JOIN tags_topics t2 ON (t.id = t2.topicId AND t2.tagId = 2)
 JOIN tags_topics t3 ON (t.id = t3.topicId AND t3.tagId = 3)

GROUP BY решение:

Обратите внимание, что вам нужно перечислить все столбцы t.* в предложении GROUP BY, если только вы не используете MySQL или SQLite.

SELECT t.*
FROM topics t JOIN tags_topics tt 
  ON (t.id = tt.topicId AND tt.tagId IN (1,2,3))
GROUP BY t.id, ...
HAVING COUNT(*) = 3;

Решение для подзапроса:

SELECT t.*
FROM topics t
WHERE t.id = ANY (SELECT topicId FROM tags_topics tt WHERE tt.tagId = 1)
  AND t.id = ANY (SELECT topicId FROM tags_topics tt WHERE tt.tagId = 2)
  AND t.id = ANY (SELECT topicId FROM tags_topics tt WHERE tt.tagId = 3);

Измененное GROUP BY решение:

Упрощает предложение GROUP BY, изолируя поиск в подзапросе.

SELECT t.*
FROM topics t
WHERE t.id IN (
  SELECT tt.topicId FROM tags_topics tt 
  WHERE tt.tagId IN (1,2,3))
  GROUP BY tt.id HAVING COUNT(*) = 3
);
person Bill Karwin    schedule 15.03.2009
comment
COUNT(*) должен быть › 2, потому что темы могут иметь и другие теги. Спасибо за все предложения! Отредактируйте это, и я установлю это как правильный ответ;) - person finpingvin; 15.03.2009
comment
@finpingvin - остальные теги в выписке не учитываются. COUNT(*) = 3 будет правильным, если в таблице соединений нет дубликатов. - person Russ Cam; 15.03.2009
comment
Да, я предполагаю, что tags_topics имеет первичный ключ над {topicId, tagId}. Кстати, я отредактировал четвертое решение, чтобы избежать соединения внутри подзапроса, после прочтения решения @Russ Cam. - person Bill Karwin; 15.03.2009

person    schedule
comment
+1 за то, что вы избегаете соединения, используя только таблицу пересечений. Это обеспечивает соответствующие значения topic_id, но не полный объект темы. - person Bill Karwin; 15.03.2009