SQL выбирает посты без определенного тега

0

Прямо к сути. У меня три таблицы POSTS, TAGS, POST_TAGS

POSTS { p_id, title }
TAGS { t_id, name }
POST_TAGS { p_id, t_id }

Одна почта может иметь несколько тегов, и я хочу выбрать все сообщения, у которых нет определенного тега. например, возьмите эти демо-данные:

TASKS
p_id | title
1      MyPost 1
2      MyPost 2
3      MyPost 3

TAGS
t_id | name
1      red
2      green

POST_TAGS
p_id | t_id
1      1
2      1
2      2
3      2

Теперь я хочу видеть все POSTS, у которых нет TAG 'green'. Мой текущий запрос SQL выглядит так:

SELECT DISCTINCT
   p.p_id, p.title 
FROM
   POSTS as p,
   POST_TAGS as pt
WHERE 
   pt.p_id = p.p_id AND pt.t_id != 2 

но это вернет мне это

RESULT
p_id | title
1      MyPost 1
2      MyPost 2

потому что "MyPost 2" также имеет красный цвет TAG, это список.

Желаемый результат:

RESULT
p_id | title
1      MyPost 1

EDIT: Спасибо всем вам, ребята, я принял GarethD ответ, потому что NOT EXISTS более понятен. NOT IN работает, но не сохраняет NULL (даже если я не просил об этом - благодаря Нико Хаазе)

Решение GermanC также корректно и работает, но не так понятно, как выбранный ответ. и тебе спасибо.

Теги:
database
many-to-many

3 ответа

3
Лучший ответ

Вы можете сделать это, используя NOT EXISTS:

 SELECT p.p_id, p.title 
 FROM   POSTS AS p
 WHERE  NOT EXISTS 
        (   SELECT  1 
            FROM    POST_TAGS AS pt 
            WHERE   pt.p_id = p.p_id
            AND     pt.t_id = 2
        );
1

Вы можете явно присоединиться к поиску Зеленого тега и показать те сообщения, в которых соединение не было успешным:

SELECT
   p.p_id, p.title 
FROM
   POSTS as p
LEFT OUTER JOIN
   POST_TAGS as pt on pt.p_id = p.p_id AND pt.t_id = 2 
WHERE 
   pt.p_id is null
0

Это выполнит задание, поскольку оно ищет все сообщения, помеченные 2 во внутреннем запросе и исключающие их во внешнем

SELECT DISTINCT p.p_id WHERE p.p_id NOT IN(
    SELECT DISCTINCT
       p.p_id 
    FROM
       POSTS as p,
       POST_TAGS as pt
    WHERE 
       pt.p_id = p.p_id AND pt.t_id = 2
)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню