Потому что тег ID=3 принадлежит не только посту 33. Вот и получаете что есть запись в которой он принадлежит и запись в которой не принадлежит. А если будет 3 поста - будет 3 такие записи (в одной принадлежит и в двух не принадлежит) и т.д.
У меня такой вопрос: зачем вам список тегов, которые не принадлежат посту? Обычно интересуют именно те, которые принадлежат. И обязательно ли это делать одним запросом?
Получить список тегов, которые принадлежат посту:
SELECT t.* FROM tags t
JOIN posts_tags pt ON pt.tag_id=t.id
WHERE pt.post_id=:post_id
Получить список тегов, которые не принадлежат посту:
SELECT t.* FROM tags t
LEFT JOIN posts_tags pt ON pt.tag_id=t.id AND pt.post_id=:post_id
WHERE pt.id IS NULL
Если хочется завернуть это в один запрос - добавляете колонку have_tag (в первом запросе - 1, во втором - 0) и делаете UNION.