Как исключить строку в отношении «один ко многим» между таблицами (SQL-запрос)

У меня есть две таблицы: Products и ProductTags (у меня также есть теги таблиц, которые не являются частью проблемы)

Мой запрос

SELECT
product.id
FROM
Products JOIN ProductTags ON Products.id = ProductTags.product_id
WHERE ProductTags.tag_id = 10  and ProductTags.tag_id <> 20

Таблица ProductTags — это связь один-ко-многим между product_id и tag_id, если она так называется. Допустим, вся таблица ProductTags:

Код товара tag_id 777 10 777 20 888 10 888 30

в результате моего запроса я получаю 777 и 888. Но я хочу исключить продукты с тегом № 20. В реальном запросе я также присоединяюсь к другим таблицам (также мне нужен доступ к другим полям таблицы продуктов), поэтому я НЕ МОГУ получить правильный результат, используя только таблицу ProductTags! Я знаю, что я мог бы сделать это как

SELECT product_id ProductTags WHERE tag_id = 10

но это НЕ БУДЕТ правильным решением!

Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
1
0
659
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Один из способов — использовать агрегацию.

SELECT product_id id
       FROM producttags
       WHERE tag_id IN (10,
                        20)
       GROUP BY product_id
       HAVING max(tag_id) = 10;

Другой использует NOT EXISTS и коррелированный подзапрос.

SELECT pt1.product_id
       FROM producttag pt1
       WHERE pt1.tag_id = 10
             AND NOT EXISTS (SELECT *
                                    FROM producttag pt2
                                    WHERE pt2.product_id = pt1.product_id
                                          AND pt2.tag_id = 20);

Обратите внимание, что объединение product не требуется только для получения идентификаторов продуктов, если только для producttags.product_id нет надлежащего ограничения внешнего ключа.

Спасибо! использование NOT EXISTS помогло мне, теперь это работает как отступ!

Alex R 23.12.2020 14:15
SELECT product.id
FROM Products 
JOIN ProductTags ON Products.id = ProductTags.product_id
GROUP BY product.id
HAVING SUM(ProductTags.tag_id = 10) > 0 -- at least one
   AND SUM(ProductTags.tag_id = 20) = 0 -- none

Эта форма допускает любое количество простых или сложных условий.

Например:

-- strictly one row with tag_id = 30
   AND SUM(ProductTags.tag_id = 30) = 1
-- at least one tag_id 40 or 50
   AND SUM(ProductTags.tag_id IN (40, 50)) > 0
-- ... and so on

Другие вопросы по теме