これが基本的な多対多のselectステートメントです。
select s.*, t.*
from songs s
join songs_tags st on s.songId = st.songId
join tags t on t.tagId = st.tagId
-- optional where clause
where s.name = 'my song'
where句がタグベースの場合は、それを裏返します
select s.*, t.*
from tags t
join songs_tags st on s.songId = st.songId
join songs s on s.songId = st.songId
-- optional where clause
where t.name = 'whatever'
複数のタグが付いたすべての曲を返す場合は、where句を変更するだけです。
select s.*
from tags t
join songs_tags st on s.songId = st.songId
join songs s on s.songId = st.songId
where t.name in ('tag1', 'tag2', 'tag3')
名前とタグで検索する場合など、特定のタグが付いた特定の曲を返す
select s.*, t.*
from songs s
join songs_tags st on s.songId = st.songId
join tags t on t.tagId = st.tagId
where s.name like '%mysong%' and t.name in ('tag1', 'tag2')
結合テーブル自体をフィルタリングすることもでき、必要な場合もあります。
select s.*, t.*
from songs s
join songs_tags st on s.songId = st.songId
join tags t on t.tagId = st.tagId and t.name in ('tag1', 'tag2')
where s.name like '%mysong%'
タグのない曲を検索するには
select s.*
from songs s
left join songs_tags st on s.songId = st.songId
where st.songId is null
すべてのタグが付いている曲を検索するには:
select s.*
from songs s
join songs_tags st1 on s.songid = st1.songid
join songs_tags st2 on s.songid = st2.songid
join songs_tags st3 on s.songid = st3.songid
where st1.tagid = 1 and st2.tagid = 2 and st3.tagid = 3