views:

38

answers:

3

Given a model like this alt text

ProductFacets contains the following data:

ProductId, FacetTypeId
1, 1
1, 2
2, 1
2, 3
3, 4
3, 5
4, 1
4, 2

I'd like to be able to select all Products which have a FacetTypeId of 1 AND 2. The result set should contain ProductIds 1 and 4

A: 
SELECT * FROM Product PROD WHERE PROD.ProductId IN(

SELECT P.ProductId pId FROM ProductFacets AS P 
WHERE P.FacetTypeId = 1 

AND EXISTS  
(
  SELECT *
  FROM ProductFacets AS P1 
  WHERE P1.FacetTypeid = 2 
        AND P1.ProductId = pId
)

AND NOT EXISTS  
(
  SELECT *
  FROM ProductFacets AS P2 
  WHERE P2.FacetTypeid NOT IN (1,2) 
        AND P2.ProductId = pId
)

)

There must be a better way to solve this, but it's the only one i can come up with

mcabral
+1  A: 

This will return rows for products that have only facet types 1 and 2, and only those facets.

SELECT ProductId,
    COUNT(*) AS FacetCountByProduct,
    SUM(CASE WHEN FacetTypeId in (1, 2) THEN 1 ELSE 0 END) AS FacetCountSelectedFacets
FROM ProductFacets
GROUP BY ProductId
HAVING COUNT(*) = 2
    and SUM(CASE WHEN FacetTypeId in (1, 2) THEN 1 ELSE 0 END) = 2
;
bobs
A: 

Just thought of a way to do this:

select distinct ProductId from ProductFacets 
where ProductId in (select ProductId from ProductFacets where FacetTypeId = 1)
and ProductId in (select ProductId from ProductFacets where FacetTypeId = 2)
sf

related questions