I working on a tag based search. I have three tables tag(id,name), tagXmedia(id,tag_id,media_id), and media(id,...). tagXmedia is the mapping table between the tag and media
@kba's answer is correct but you can also do this with a JOIN which is probably more efficient.
SELECT media_id
FROM tagXmedia
LEFT JOIN tag ON tag_id = tag.id
WHERE tag.name IN ('home', 'hawaii')
GROUP BY media_id
HAVING COUNT(tag_id) = 2;
I had a similar problem where I wanted to get not just the media_id
but the actual object and wanted to pass in arbitrary comma separated lists of tags. Here's my complete solution using a stored procedure:
CREATE PROCEDURE FindByTag(IN _tags VARCHAR(256))
BEGIN
DECLARE _length INT;
-- Get the length of the list
SET _tags = TRIM(BOTH ',' FROM _tags);
SET _length = LENGTH(_tags) - LENGTH(REPLACE(_tags, ',', '')) + 1;
-- Find media
SELECT * FROM media
WHERE id IN (
SELECT media_id FROM tagXmedia
LEFT JOIN tag ON tag_id = tag.id
WHERE FIND_IN_SET(tag.name, _tags)
GROUP BY media_id
HAVING COUNT(tag_id) = _length
)
END