Попробуйте:
select book_id
from categories
group by book_id
having sum( ( cat_id in (1,3) )::int ) = 2
Или, если вы намереваетесь передать массив в postgres из языка, который поддерживает передачу массива непосредственно в него (например: http://fxjr.blogspot.com/2009/05/npgsql-tips-using-in-queries-with.html),, используйте это:
select book_id
from categories
group by book_id
having sum( ( cat_id = ANY(ARRAY[1,3]) )::int ) = 2
Если вы хотите получить название книги:
select categories.book_id, books.name
from categories
join books on books.id = categories.book_id
group by categories.book_id
,books.name
having sum( ( categories.cat_id in (1,3) )::int ) = 2
@ Эван Кэрролл, исправляя запрос:
Способ ANSI SQL:
select categories.book_id, books.name
from categories
join books on books.id = categories.book_id
group by categories.book_id
,books.name
having count(case when categories.cat_id in (1,3) then 1 end) = 2
без названия книги:
select book_id
from categories
group by book_id
having count( case when cat_id in (1,3) then 1 end ) = 2
В чем преимущество включения условия и его значения счетчика в одном и том же предложении (т. Е. having
) по сравнению с раздельным помещением условия в предложении where
и его количеством в предложении having
? ...
select book_id
from categories
where category_id in (1,3)
group by book_id
having count(*) = 2
... Если мы включим в условие having
и условие, и его значение счетчика, мы можем упростить запрос, скажем, списка всех книг с категориями 1 и 3 или с категориями 2 и 3 и 4 . Перспективный FTW! Плюс тестирование объединенных категорий и их количество рядом друг с другом, плюс фактор с точки зрения читабельности.
Чтобы упростить такой запрос:
select book_id
from categories
group by book_id
having
count( case when cat_id in (1,3) then 1 end ) = 2
or count( case when cat_id in (2,3,4) then 1 end ) = 3
Для достижения производительности (иногда достижения как производительности, так и читабельности; плохо сочетаются), должен продублировать тестирование элементов, имеющих предложение, к предложению where:
select book_id
from categories
where cat_id in (1,2,3,4)
group by book_id
having
count( case when cat_id in (1,3) then 1 end ) = 2
or count( case when cat_id in (2,3,4) then 1 end ) = 3
[EDIT]
Кстати, вот идиоматический MySQL:
select book_id
from categories
group by book_id
having sum( cat_id in (1,3) ) = 2