Найти только записи, которые относятся ко всем категориям

В PostgreSQL у меня есть 3 таблицы:

  1. Таблица статей
  2. Таблица категорий
  3. Таблица, которая сопоставляет статьи с категориями

Я хочу иметь возможность находить статьи, относящиеся ко всем категориям, не зная, какие категории существуют.

Конкретный пример:

articles      categories        
| id    |     | id    | name  | 
+-------+     +-------+ ------+ 
| 1     |     | 1     | cat 1 | 
| 2     |     | 2     | cat 2 | 
| 3     |     | 3     | cat 3 | 


category map       
| article_id | category_id  |
+------------+--------------+
| 1          | 1            |
| 1          | 2            |
| 1          | 3            |
| 2          | 1            |
| 2          | 2            |

В этом случае статья, соответствующая критериям, является только статьей 1. Статья 2 не соответствует, поскольку относится только к категориям 1 и 2. Статья 3 не соответствует, поскольку не принадлежит ни к какой категории.

Если я затем добавлю другую категорию в список категорий, никакие статьи не будут совпадать. Таким образом, запрос будет зависеть от списка категорий в таблице категорий.

Я не уверен, как подойти к этому в целом.

Я думал об использовании перекрестного соединения, но общий характер таблицы категорий доставляет мне проблемы.


person martineno    schedule 20.05.2020    source источник
comment
Это предполагает относительное деление. Это часто задаваемые вопросы. Хотя это и не так просто найти, потому что люди не могут составить четкое, краткое и полное изложение того, что они хотят сделать. (Как здесь.) Тем не менее: прежде чем рассматривать публикацию, пожалуйста, прочитайте учебник и/или руководство и погуглите любое сообщение об ошибке или много четких, кратких и точных формулировок вашего вопроса/проблемы/цели, с вашими конкретными строками/именами и сайтом и без них: stackoverflow.com и теги; прочитал много ответов. Если вы публикуете вопрос, используйте одну фразу в качестве заголовка. Отразите свое исследование. См. раздел Как задать вопрос и тексты при наведении указателя мыши на стрелку голосования.   -  person philipxy    schedule 20.05.2020
comment
В вашей спецификации есть классическая двусмысленность, связанная с запросами, включающими и почти включающими реляционное разделение. Вы говорите статьи, которые относятся ко всем категориям. Если нет категорий, вам нужны все статьи или ни одной? Первые — это статьи, для которых они есть в каждой категории, а вторые — добавляют… и они находятся в категории — относительном подразделении. Для цитируемой фразы можно подумать, что если нет категорий, то нет и принадлежности, значит, нет статей, следовательно, нет; но мы не знаем, намеренно ли это тонкое различие. Об этом говорится в статьях отдела.   -  person philipxy    schedule 20.05.2020


Ответы (1)


Вы можете использовать приведенный ниже запрос.

SELECT ARTICLE_ID FROM CATEGORY_MAP
WHERE CATEGORY_ID IN (SELECT ID FROM CATEGORIES)
GROUP BY ARTICLE_ID
HAVING COUNT(DISTINCT CATEGORY_ID) = (SELECT COUNT(*) FROM CATEGORIES);

Как вы упомянули, это возьмет все категории из таблицы categories и проверит Category_map, все ли они доступны, а затем выдаст только article_id со всеми категориями.

Проверьте демо здесь

person Arun Palanisamy    schedule 20.05.2020