SQL查询有很多对很多关系

时间:2012-06-06 11:28:17

标签: mysql

我正在尝试创建一个可以在多对多关系数据库中获取结果的查询 到目前为止,我得到以下内容:
一张带有歌曲的表格,一张带有标签的表格和一张“链接”表作为一首歌曲可以有多个标签,一个标签可以属于多首歌曲。

它看起来像这样:

Songs       Link        Tags
=======     =====       =========
Sid          Sid        Tid
Songname     Tid        Tagname

现在假设您有3首歌曲A B和C以及3个标签:X,Y和Z. 歌曲A具有标签Y,歌曲B具有标签Z,歌曲C具有标签X和Z。

我设法创建了一个只通过一个标签来获取歌曲的查询(例如Z给出了B和C) 但是,如何在输入多个标签时创建搜索歌曲的查询(例如,键入(搜索)字段)。

我已经搜索了几次命令INTERSECT和INNER JOIN,但我还没能成功创建一个查询。

感谢任何帮助!

5 个答案:

答案 0 :(得分:4)

这是您的基本多对多选择语句。

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

答案 1 :(得分:3)

这首歌将获得与任何标签匹配的所有歌曲,并返回首先匹配所有歌曲的歌曲:

SELECT s.Sid, s.Songname
FROM Songs s
JOIN Link l ON ( l.Sid = s.Sid )
JOIN Tags t ON ( t.Tid = s.Tid )
WHERE t.Tagname IN ( 'X', 'Y' )
GROUP BY s.Sid, s.Songname
ORDER BY COUNT(1) DESC

此歌曲只返回符合所有标签的歌曲:

SELECT s.Sid, s.Songname
FROM Songs s
JOIN Link l ON ( l.Sid = s.Sid )
JOIN Tags t ON ( t.Tid = s.Tid )
WHERE t.Tagname IN ( 'X', 'Y' )
GROUP BY s.Sid, s.Songname
HAVING COUNT(1) = 2 -- 'X' and 'Y'

如果您生成此查询,则还必须生成计数(在我的情况下为2)。

答案 2 :(得分:2)

SELECT DISTINCT s.Sid, s.Songname 
FROM 
    Songs s join Link l on s.Sid=l.Sid 
    join Tags t on t.Tid=l.Tid 
WHERE t.Tagname in ('Z', 'Y');

这将返回所有标记为Z或Y

的歌曲

答案 3 :(得分:1)

select distinct songs.* 
from songs 
inner join link on link.sid = songs.sid 
inner join tags on tags.tid = link.tid
where tagname IN ('a','b','c')

这样的事情?

答案 4 :(得分:0)

你可以尝试这个 -

select a.Sid, a.SongName, c.Tid, c.TagName  
from Songs a
LEFT OUTER JOIN Links b ON a.Sid = b.Sid 
LEFT OUTER JOIN Tags c ON b.Tid = c.Tid 
WHERE c.TagName IN ('Tag1', 'Tag2', ...... ) // as many tags you want 
group by a.Sid, a.SongName, c.Tid, c.TagName