Используйте ограничение "IN", но добавьте его, чтобы убедиться, что количество совпадений категорий равно количеству всех категорий, которые вы ищете, чтобы убедиться, что все категории соответствуют и не просто подмножество.
В качестве примера того, что я имею в виду, вы можете взглянуть на эту страницу , особенно на запрос "Пересечение" под заголовком "Решение Toxi". Замените «закладки» на «статьи» и «теги» на «категории», чтобы сопоставить это с вашей конкретной проблемой. Вот SQL, который они показывают там:
SELECT b.*
FROM tagmap bt, bookmark b, tag t
WHERE bt.tag_id = t.tag_id
AND (t.name IN ('bookmark', 'webservice', 'semweb'))
AND b.id = bt.bookmark_id
GROUP BY b.id
HAVING COUNT( b.id )=3
Полагаю, вы также можете представить это с помощью подзапроса, который проще представить с помощью API Criteria
SELECT Article.Id
FROM Article
INNER JOIN (
SELECT ArticleId, count(*) AS MatchingCategories
FROM ArticleCategoryMap
WHERE CategoryId IN (<list of category ids>)
GROUP BY ArticleId
) subquery ON subquery.ArticleId = EntityTable.Id
WHERE subquery.MatchingCategories = <number of category ids in list>