views:

271

answers:

3

A very simple example of a n:m relationship that puzzles me. Let's assume we have two tables "Plant" and "Attribute" and another table between them holding their relationship with their IDs:

Plant--------hasAttribute--------Attribute
               P1 | A1
               P1 | A2
               P1 | A3
               P2 | A1
               P2 | A2
               P3 | A2
               P3 | A3

So, Plant 1 has Attributes 1,2 and 3. Plant 2 has Attributes 1 and 2 and Plant 3 has Attributes 2 and 3. Now, in one single query, how can I get e.g. all the Plants that have Attribute 2 and 3? The result should return P1 and P3 because they both have Attributes 2 and 3. I was trying union but that will give me P2 as a result as well... any ideas?

+2  A: 

http://stackoverflow.com/questions/1202668/problem-with-sql-query

Is this what your looking for?

Paul Janaway
Actually it is the same problem, I just don't get why the count distinct. It does give me the required result, but I always have to put the number of attribute in the count distinct that i am making the query with...
Dimitri Wetzel
A: 
select * from Plants p where 2 = ( 
  select count(*) from HasPlants h
     where h.pid = p.id and h.aid in ( a2, a3 ) 
  )
palindrom
IN clause is the equivalent to OR - you'd get a count of those with 'a2' or 'a3', not both.
OMG Ponies
@rexem: there can be at most one a2 and at most one a3 for a pid. A count of 2 means it has both.
palindrom
A: 

This query structure avoids the need for a distinct clause (provided there are no duplicate records in the resolution table).

SELECT p.PlantID
FROM
  Plant p INNER JOIN PlantAttribute pa
    ON p.PlantID = pa.PlantID AND pa.AttributeID = 1
  INNER JOIN PlantAttribute pa2
    ON p.PlantID = pa2.PlantID AND pa2.AttributeID = 2;
codemonkey