我有三个表:‘视频’,‘标签’和‘链接’。下面是一个链接表的示例:
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‘的视频。为了找到包含标签1和4的视频,我添加了HAVING sum(tagid = 1) > 0 AND sum(tagid = 4) > 0。它会返回最后两段视频。这是一个类似问题的解决方案。使用WHERE子句对我来说会更方便,所以我正在寻找WHERE的答案。
发布于 2017-11-04 20:22:09
您可以使用in子句筛选所需的标记,并使计数()等于所需的标记数,例如对于两个名为tagid1,tagid2的tagid
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个标记的视频,但也需要其他的,则应该删除having子句。
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或者您可以使用一个in子句,即视频tha匹配tha标记。
SELECT v.id, GROUP_CONCAT(l.tagid) as tags
FROM videos v
where v.id in (
select videos.id
from videos
INNER JOIN links on links.videoid = video.id
and links.tagid in ( tagid1, tagid2)
)
GROUP BY v.id发布于 2017-11-08 22:31:12
据我所知,您的实际工作查询是
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只要表不太大,这(IMHO)就很好了。但是,有了这个条件,您的连接就在逻辑上成为了一个内部连接。如果您只需要视频的id,您可以选择l.videoid而不需要触摸videos表。
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)的索引,执行计划应该是:
links (l1)和tagid = 1 (在索引(tagid, videoid)中搜索)查找所有行links (l2)查找tagid = 4中的所有行,在l1中查找与l1中相同的行(在索引(tagid, videoid)中搜索),然后跳过所有行而不匹配。links (l)中查找与l1和l2中相同的videoid中的所有行,并按videoid对它们进行分组(使用索引(videoid, tagid)进行搜索和分组)如果您需要的不仅仅是videoid,还可以加入videos表。
JOIN videos v ON v.id = l.videoid然后从那张桌子上选择你需要的东西。
https://stackoverflow.com/questions/47115107
复制相似问题