There are two tables:
Packages
id name
1 red
2 blue
3 yellow
Contents
packageid item size
1 square A
1 circle B
1 triangle C
2 square A
2 circle B
3 square A
If we query for { item:square, size:A }
we only want { packages.id:3 }
If we query for { item:square, size:A }
and { item:circle, size:B }
we only want { packages.id:2 }
If we query for { item:square, size:A }
and { item:circle, size:B }
and { item:triangle, size:C }
we only want { packages.id:1 }
If there is more than one package that matches exactly, we would like all of them.
This seems to work, but it’s not terribly elegant:
SELECT
p.id,
p.name,
c.item,
c.size
FROM Packages p
LEFT JOIN Contents c ON (
c.packageid=p.id
)
WHERE (
( p.id IN ( SELECT packageid FROM Contents WHERE item='square' AND size='A' )
AND
( p.id IN ( SELECT packageid FROM Contents WHERE item='circle' AND size='B' )
)
GROUP BY p.id
HAVING ( SELECT COUNT(*) FROM Contents WHERE packageid=p.id ) = 2;
2
Answers
With
EXISTS
, you will get your wanted resultsfiddle
We can achieve this using some CTEs :
Explanations :
The first CTE, the condition(s) will be passed as a dataset.
The second CTE count the rows using the window function
COUNT()
.The third CTE was used to combine the two tables and count total rows per package.
Finally, in order to obtain the desired result, we must join our filter rows with the combined data by item, size, and count.
Which for this condition
Results :
Demo here