3

多対多の関係データベースで結果を取得できるクエリを作成しようとしています。
これまでのところ、次のようになりました:
曲を含む 1 つのテーブル、タグを含む 1 つのテーブル、および 1 つの曲が複数のタグを持つことができ、1 つのタグが複数の曲に属することができる「リンク」テーブル。

次のようになります。

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

ここで、AB と C の 3 つの曲と X、Y、Z の 3 つのタグがあるとします。
曲 A にはタグ Y、曲 B にはタグ Z、曲 C にはタグ X と Z があります。

たった 1 つのタグで曲を取得するクエリを作成できました (たとえば、Z は B と C を返します)。
しかし、複数のタグが入力されたときに曲を検索するクエリを作成するにはどうすればよいですか (たとえば、(検索) フィールドに入力します)。

検索したところ、コマンド INTERSECT と INNER JOIN が数回出てきましたが、クエリを正常に作成できませんでした。

どんな助けでも大歓迎です!

4

5 に答える 5

5

これが基本的な多対多の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
于 2012-06-06T11:33:31.380 に答える
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私の場合)。

于 2012-06-06T11:41:26.657 に答える
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 のいずれかのタグを持つすべての曲が返されます

于 2012-06-06T11:32:38.327 に答える
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')

このようなもの?

于 2012-06-06T11:33:07.690 に答える
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 
于 2012-06-06T11:46:06.043 に答える