views:

78

answers:

2

I'm creating a database that's going to contain various artists which can be tagged with several tags. It's a standard many-to-may relation and my database looks like this:

artist:  
 ID
 name  

tag:
 ID
 name

tagID:
 tagID
 artistID

Say I've got two tagIDs, X and Y. What I want to do is to find all the tags that have an artist in common with tag X and Y. How do I do this?

Ultimately what I want this to turn into is an interface that let's you find an artist that's tagged with an arbitrary set of tags. To make the process simpler I want to filter out combinations of tags that will not give any result.

+1  A: 
SELECT T.tagID
  FROM tagID T
  WHERE T.artistID IN (SELECT T1.artistID
                          FROM tagID T1,
                               tagID T2,
                          WHERE T1.tagID = X AND
                                T2.artistID = T1.artistID AND
                                T2.tagID = Y)

Share and enjoy.

Bob Jarvis
Looks promising, but I'm having some problems understanding your code. What do you mead by T1 and T?
Paul
Alias names for the tables. tagID = T1 in the outer query, and in the subquery tagID = T. It helps clarify which instance of the table the column names are coming from.
Jacob Ewald
Got this working now and it's just what I need. Thanks a lot!
Paul
But does this require that the artist has both X and Y? It looks like it will select any artist who has X or Y.
Ray
Ah, I didn't see Paul's comment to the original question when I wrote my answer. No, my answer doesn't require that the artist have both X and Y. Gotta fix that.
Bob Jarvis
OK, I edited the SQL so it requires both tags X and Y.
Bob Jarvis
APC's 'intersect' solution works, but the sql would need to be dynamically generated each time for each different set of tags.
Ray
A: 

This solution uses the INTERSECT set operator to identify TagID records for Artists who have both tag X and tag Y. If you work with a flavour of database which doesn't support that set operator you'll have to use a normal join instead.

select distinct tagid
from   tagid 
where tagid not in ('X', 'Y')
where artistid in 
        ( select artistid
          from tagid 
          where tagid = 'X'
        intersect
        select artistid
          from tagid 
          where tagid = 'Y' )
/
APC