2017-11-04 9 views
0

私は3つのテーブル: 'videos'、 'tags'、 'links'を持っています。ここでは、リンクテーブルの例である:MYSQLを使用してIDのリストで検索する

mysql> select * from links; 
+----+-------+---------+ 
| id | tagid | videoid | 
+----+-------+---------+ 
| 25 |  6 |  35 | 
| 24 |  5 |  7 | 
| 23 |  1 |  7 | 
| 22 |  7 |  3 | 
| 21 |  1 |  3 | 
+----+-------+---------+ 
5 rows in set (0.00 sec) 

私はこのクエリを使用し、各ビデオのタグリストを取得するには:

SELECT v.id, GROUP_CONCAT(l.tagid) as tags FROM videos v LEFT JOIN links l ON l.videoid = v.id GROUP BY v.id; 
+----+------+ 
| id | tags | 
+----+------+ 
| 30 | NULL | 
| 31 | 2 | 
| 32 | 1,3 | 
| 33 | 1 | 
| 34 | 1,2 | 
+----+------+ 
5 rows in set (0.02 sec) 

しかし、どのように、私はタグのリストを含む、動画を検索することができますか?現在私はクエリの最後にHAVING句を追加します。

たとえば、タグ「1」、「1,4」、「1,4,7」の3つの動画があります。タグ1と4を含む動画を検索するには、HAVING sum(tagid = 1) > 0 AND sum(tagid = 4) > 0を追加します。最後の2つの動画が返されます。これは同様の質問からの解決策です。 WHERE句を使用するほうが便利なので、私はWHEREで答えを探しています。

+0

両方のタグ(1と4)を持つ動画が必要ですか? –

+0

@PaulSpiegel、はい、複数のタグを検索したい – h0rn3t

答えて

1

あなたはまた、必要そうでない場合句に必要なタグカウント(disctinctタグID)を有するが、あなたがtagid1、tagid2

SELECT v.id, GROUP_CONCAT(l.tagid) as tags 
FROM videos v 
where l.tagid in( tagid1, tagid2) 
LEFT JOIN links l ON l.videoid = v.id GROUP BY v.id 
having count(dictinct tagid) = 2; 

という名前の2個のタグIDのために例えば必要なタグの数に等しいとするためにフィルタリングすることができ2個のタグだけでなく、他の人が含まれているビデオは、あなたが持つ句

SELECT v.id, GROUP_CONCAT(l.tagid) as tags 
FROM videos v 
where l.tagid in( tagid1, tagid2) 
LEFT JOIN links l ON l.videoid = v.id GROUP BY v.id 

それとも句でビデオTHAマッチ股関節タグ

を使用することができますを削除する必要があります3210
+0

この場合、タグの数が増えても、 'tags'カラムには' tagid1'と 'tagid2'しか含まれません。 –

+0

@PaulSpiegel。答えが更新されました。多くのありがとう – scaisEdge

+0

thxは答えていますが、2番目のクエリはtagid1、tagid2、およびその両方だけを含む動画を返します。しかしビデオは両方のタグを持っている必要がありますまた、より多くのタグを持つことができる、私はあなたが望む結果を見ることができるように答えを更新しました – h0rn3t

0

私は理解しているように、あなたの実際の作業クエリが

SELECT v.id, GROUP_CONCAT(l.tagid) as tags 
FROM videos v 
LEFT JOIN links l ON l.videoid = v.id 
GROUP BY v.id 
HAVING sum(tagid = 1) > 0 
    AND sum(tagid = 4) > 0 

これ(私見)がいる限り、テーブルが大きすぎないようだけで結構です。しかし、このHAVING条件では、JOINは論理的にINNER JOINになります。また、動画のうちidだけが必要な場合は、videosの表に触れることなくl.videoidを選択できます。

SELECT l.videoid, GROUP_CONCAT(l.tagid) as tags 
FROM links l 
GROUP BY l.videoid 
HAVING sum(tagid = 1) > 0 
    AND sum(tagid = 4) > 0 

しかし、これは大きなデータセットでのパフォーマンスの問題かもしれないlinksテーブル上の全表スキャンが必要です。パフォーマンスを向上させるためには、次のクエリを試すことができます。

SELECT l.videoid, GROUP_CONCAT(l.tagid) as tags 
FROM links l 
JOIN links l1 USING(videoid) 
JOIN links l2 USING(videoid) 
WHERE l1.tagid = 1 
    AND l2.tagid = 4 

考えるlinks(tagid, videoid)links(videoid, tagid)上のインデックス実行計画は次のようになります。

  • がインデックスにtagid = 1(検索でlinksl1)内のすべての行を検索(tagid, videoid)
  • tagid = 4とと同じvideoidで)linksl2内のすべての行を検索10(インデックス(tagid, videoid)で検索)、一致しないすべての行をスキップします。
  • は、(検索やGROUP BYのために使用インデックス(videoid, tagid)videoidによってl1l2やグループ、それらと同じvideoidlinksl)のすべての行を検索

あなただけvideoid以上のものを必要とする場合videosテーブルに参加することができます

JOIN videos v ON v.id = l.videoid 

このテーブルから必要なものを選択してください。

関連する問題