3

From the table below, how would I select all animalIds that have a specific combination of attributeIds e.g. if I supplied attributeIds 455 & 685 I'd expect to get back animalIds 55 & 93

Table name: animalAttributes

id      attributeId     animalId
1       455             55
2       233             55
3       685             55
4       999             89
5       455             89
6       333             93
7       685             93
8       455             93

I have the following query that seems to work, however, I'm not sure if there is a more robust way?

  SELECT animalId
    FROM animalAttributes
   WHERE attributeId IN (455,685)
GROUP BY animalId 
  HAVING COUNT(DISTINCT attributeId) = 2;
6
  • I think this query will not give you what you want. It is conceivable for an animal to have 455 attribute, and another, say, 123. This would return since it has two. Commented May 31, 2011 at 23:40
  • 123 wouldn't be in the criteria, so wouldn't be included. Commented May 31, 2011 at 23:41
  • There's no need for Having clause HAVING COUNT(DISTINCT attributeId) = 2 Commented May 31, 2011 at 23:42
  • The having clause is ensuring they have both attributes. This query looks OK to me. Commented May 31, 2011 at 23:45
  • I think if (attributeId, animalId) is unique, you don't need the DISTINCT. Commented May 31, 2011 at 23:50

3 Answers 3

1

If you really want accurate results, you could go with a fool-proof method like this:

select distinct base.animalId
from animalAttributes base
join animalAttributes a on base.animalId = a.animalId
     and a.attributeId = 455
where base.attributeId = 685

If you later needed 3 matching attributes, you could just add another join:

select distinct base.animalId
from animalAttributes base
join animalAttributes a on base.animalId = a.animalId
     and a.attributeId = 455
join animalAttributes b on base.animalId = b.animalId
     and b.attributeId = 999
where base.attributeId = 685
Sign up to request clarification or add additional context in comments.

2 Comments

when you say "fool-proof", how is this more robust? Thanks
@raider5 it was directed at the OPs query that he says 'seems to work.' Also some of the other answers don't give me the warm fuzzies that they will work.
1
SELECT DISTINCT `animalId` FROM `animalAttributes` WHERE `attributeId` = 455
INTERSECT
SELECT DISTINCT `animalId` FROM `animalAttributes` WHERE `attributeId` = 685

Comments

1
SELECT DISTINCT animalId
FROM animalAttributes
WHERE attributeId IN (455,685)

or

SELECT animalId
FROM animalAttributes
WHERE attributeId IN (455,685)
GROUP BY animalId

2 Comments

This will return animalIds even if they only have one of the attributeId values.
@MarkD - It needs to be based on a combination of 455 AND 685 rather than 455 OR 685. I'm guessing your query would return animalIds 55,89,93?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.