Essayez:
select book_id
from categories
group by book_id
having sum((cat_id in (1,3))::int) = 2
Ou si vous avez l'intention de passer un tableau à postgres de langage qui prend en charge passant array directement à lui (comme ceci: http://fxjr.blogspot.com/2009/05/npgsql-tips-using-in-queries-with.html), utilisez ceci:
select book_id
from categories
group by book_id
having sum((cat_id = ANY(ARRAY[1,3]))::int) = 2
Si vous voulez obtenir le nom du livre:
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
Carroll @ Evan, modifiant la requête:
ANSI chemin 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
Sans le nom du livre:
select book_id
from categories
group by book_id
having count(case when cat_id in (1,3) then 1 end) = 2
Quel est l'avantage de inline la condition et sa valeur de comptage dans la même clause (i.e..having
) par opposition à mettre séparément la condition where
clause et son compte dans having
clause? ...
select book_id
from categories
where category_id in (1,3)
group by book_id
having count(*) = 2
... Si nous en ligne à la fois la condition et sa valeur de comptage dans having
clause, nous pouvons faciliter un enquête de disons liste tous les livres avec des catégories de 1 et 3, ou avec des catégories de 2 et 3 et 4. Future-proofing FTW! De plus, les tests des catégories combinées et leur nombre sont proches les uns des autres, plus facteur en termes de lisibilité.
Pour faciliter ce genre de requête:
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
Pour obtenir des performances (parfois, atteindre à la fois les performances et la lisibilité, ne se mélangent pas bien), doit dupliquer le test des éléments de clause having où clause:
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]
BTW, voici le idiomatiques MySQL:
select book_id
from categories
group by book_id
having sum(cat_id in (1,3)) = 2
cela semble plutôt gênant, et faux.sum est fait pour ajouter des arguments, 'count()' est fait pour compter les lignes. Voir ma réponse pour un moyen beaucoup plus facile de le faire. –
avant de dire que c'est faux, c'est un postgres idiomatique. si j'utilise mysql, je ferai ceci: 'sum (categories.cat_id in (1,3))', pour le fait que dans mysql, boolean et integer sont les mêmes, ils sont juste 1 et 0 dans les coulisses , donc plus de casting nécessaire. pour postgresql, nous avons juste besoin de convertir boolean en entier pour que les choses fonctionnent comme prévu. ok .., pour vous, je vais le rendre conforme à ANSI SQL. édition à venir –