long time lurker here, been using the advice from this site for years, and now I have a question that I can’t find an answer to – I’m sure the solution is simple though!
I’m setting up a tagging system for music tracks. I have three tables
Tracks
---------------
| id | name |
---------------
| 1 | Track1 |
| 2 | Track2 |
---------------
Taglinks
--------------------------
| id | tag_id | track_id |
--------------------------
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 2 | 2 |
--------------------------
Tags
-------------------------
| id | tag | type |
-------------------------
| 1 | acoustic | genre |
| 2 | anger | mood |
-------------------------
I want to be able to get the track name of tracks which have, for example, tag:acoustic, type:genre AND tag:anger, type:mood. So in this case I want track 1 as this has both tags.
The current query I have is
SELECT tracks.name
FROM tracks
JOIN taglinks ON tracks.id=taglinks.track_id
JOIN tags ON (tags.type='genre' AND tags.tag='acoustic') AND (tags.type='mood' AND tags.tag='anger')
WHERE taglinks.tag_id=tags.id;
This returns nothing, if I remove the AND section in the second JOIN then I get all tracks tagged acoustic as expected and if I change it to an OR I get both tracks, again as expected.
How do I do an AND though and return only those tracks that have both those tag and type?
Thanks in advance 😀
EDIT:
Just to clarify what I am after. I want to be able to retrieve tracks that have both Acoustic and Anger as tags, but only when those tags also match the given type.
This is because later I might have a tag called jazz with type genre, and a tag called jazz with type style and I need to be able to make sure I am selecting by the correct type of tag as well as the tag itself.
Here’s the link to the sqlfiddle I’m working with – http://sqlfiddle.com/#!2/aad82/3.
Gilles’s answer seems to be a good solution so far!
The problem is that the tracks should have the 2 tags equals to the asked values, all request posted yet will not work in that situation. The must should be to use the INTERSECT sql command but this one is not available in mysql.
Something like that should work :
GROUP BY.accoustic = 'genre'andanger =and found 2 rows for this track then it matches the 2'mood'
conditions and I keep it to the final result
HAVING COUNT( * ) =2with the number oftag we want to search