Использование Postgres У меня есть 3 таблицы:Исключить тег поста во многих многих запросов
CREATE TABLE post (id SERIAL, body TEXT);
CREATE TABLE tag (id SERIAL, name TEXT);
CREATE TABLE post_tag (post_id INT, tag_id INT);
INSERT INTO post(body) values('post 1');
INSERT INTO post(body) values('post 2');
INSERT INTO tag(name) values('a');
INSERT INTO tag(name) values('b');
INSERT INTO post_tag values(1, 1);
INSERT INTO post_tag values(1, 2);
INSERT INTO post_tag values(2, 1);
Таким образом post 1
имеет теги a, b
и post 2
имеет a
в качестве тега.
Вопрос: Как выбрать все сообщения, которые не имеют тег b
, то есть он должен выбрать только post 2
.
Этот запрос здесь не хорошо, потому что она будет выбирать обе должности, учитывая, что post 1
имеет 2 метки a
& b
:
SELECT post.*
FROM post
JOIN post_tag ON post_tag.post_id = post.id
JOIN tag ON tag.id = post_tag.tag_id
WHERE tag.name != 'b';
Этот запрос ниже работает, но не так, потому что, если есть тег aaaaaaab
затем его будет соответствовать этому также:
SELECT post.id, post.body, string_agg(tag1.name, ', ')
FROM post
JOIN post_tag ON post_tag.post_id = post.id
JOIN tag ON tag.id = post_tag.tag_id
GROUP BY post.id, post.body
HAVING string_agg(tag.name, ', ') not like '%b, %';
Я ищу «правильный» и эффективный подход к этому.
EDIT: Запрос также должен совпадать с сообщениями, у которых нет каких-либо тегов вообще.
Спасибо! Как насчет сообщений, у которых нет тегов? Логично также должно быть в результате. Извините, я не думал об этом раньше. –
См. Отредактированный ответ. – klin