首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >MYSQL根据ID列表使用

MYSQL根据ID列表使用
EN

Stack Overflow用户
提问于 2017-11-04 20:06:19
回答 2查看 82关注 0票数 0

我有三个表:‘视频’,‘标签’和‘链接’。下面是一个链接表的示例:

代码语言:javascript
运行
复制
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)

要获取每个视频的标记列表,我使用以下查询:

代码语言:javascript
运行
复制
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的答案。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-11-04 20:22:09

您可以使用in子句筛选所需的标记,并使计数()等于所需的标记数,例如对于两个名为tagid1,tagid2的tagid

代码语言:javascript
运行
复制
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子句。

代码语言:javascript
运行
复制
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标记。

代码语言:javascript
运行
复制
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
票数 1
EN

Stack Overflow用户

发布于 2017-11-08 22:31:12

据我所知,您的实际工作查询是

代码语言:javascript
运行
复制
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表。

代码语言:javascript
运行
复制
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表进行完整的表扫描,这可能是大数据集上的性能问题。为了获得更好的性能,您可以尝试以下查询:

代码语言:javascript
运行
复制
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)中查找与l1l2中相同的videoid中的所有行,并按videoid对它们进行分组(使用索引(videoid, tagid)进行搜索和分组)

如果您需要的不仅仅是videoid,还可以加入videos表。

代码语言:javascript
运行
复制
JOIN videos v ON v.id = l.videoid

然后从那张桌子上选择你需要的东西。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47115107

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档