Общий шаблон такой:
SELECT article_id
FROM tag2article
GROUP BY article_id
HAVING !SUM(tag_id = 1)
Подобный подход позволяет формировать условия любой степени сложности, например:
SUM(tag_id = 2) -- наличие тега 2 обязательно
SUM(tag_id IN (3,4)) -- наличие хотя бы одного из указанных тегов обязательно
!SUM(tag_id IN (5,6)) -- отсутствие любого из указанных тегов обязательно
SUM(tag_id IN (7,8)) = 1 -- обязательно наличие строго одного из двух указанных
Ну и так далее... а с учётом того, что такие условия объединяются логическими операторами, можно состряпать фильтр практически любой сложности.
Конечно, в более простых случаях можно использовать и частные решения, и они будут быстрее общего. Вот как
Сергей Паньков предложил.