Выбирает все сообщения, имеющие любой тегов (4, 10, 11):
select distinct id, title from posts
where exists (
select * from posts_tags
where
post_id = id and
tag_id in (4, 10, 11))
Или вы можете использовать это:
select distinct id, title from posts
join posts_tags on post_id = id
where tag_id in (4, 10, 11)
(оба будут оптимизированы одинаково).
Выбирает все сообщения, имеющие все тегов (4, 10, 11):
select distinct id, title from posts
where not exists (
select * from posts_tags t1
where
t1.tag_id in (4, 10, 11) and
not exists (
select * from posts_tags as t2
where
t1.tag_id = t2.tag_id and
id = t2.post_id))
Список тегов в предложении in
- это то, что динамически изменяется (во всех случаях).
Но этот последний запрос не очень быстрый, поэтому вы можете использовать что-то вроде этого:
create temporary table target_tags (tag_id int);
insert into target_tags values(4),(10),(11);
select id, title from posts
join posts_tags on post_id = id
join target_tags on target_tags.tag_id = posts_tags.tag_id
group by id, title
having count(*) = (select count(*) from target_tags);
drop table target_tags;
Часть, которая изменяется динамически, теперь находится во втором операторе (вставка).