3

我目前在我的应用程序中运行当前的 MySQL 查询最多需要 10 秒:

SELECT tagid, tag FROM tags WHERE tagid IN 
(SELECT DISTINCT tagid FROM news_tags WHERE newsid IN 
(SELECT newsid FROM news_tags WHERE tagid IN (16,32)
GROUP BY newsid HAVING COUNT(newsid)>=2)) 
AND tagid NOT IN (16,32) ORDER BY level, tagid

使用的表格是:

  • news_tags,有列newsidtagid
  • tags, 有列tagid, tag,level

查询的目的是找到标签为tagid1632 的“新闻”项目,然后找到这些新闻项目也被标记的其他标签,以便用户进一步缩小“新闻”的范围" 具有更具体标签组合的项目。最终目标是从表中获取剩余的tag相关tagidtags

我已经尝试过不同的尝试,JOIN但未能选择tagid新闻项目上附加了提供的标签的所有剩余 s。

这是我的EXPLAINSQL 结果,以防它们指出我遗漏的另一个缓慢原因:

id|select_type |table |type |possible_keys|key |key_len|ref |rows|Extra
 1|PRIMARY |标签 |范围 |PRIMARY |PRIMARY| 4|空| 55|在哪里使用;使用文件排序
 2|相关子查询|news_tags|index_subquery|tagid |tagid | 4|功能| 26|使用索引;使用哪里
 3|相关子查询|news_tags|index |tagid |PRIMARY| 8|空| 11|在哪里使用;使用索引

只是为了澄清这个问题:我想要用标签 16 和 32 标记的新闻项目的剩余标签,而不是 16 或 32。抱歉有任何混淆。

4

3 回答 3

2
SELECT DISTINCT tags.tagid, tags.tag
FROM
       tags                             -- tags from the ...
  JOIN news_tags AS n0 USING (tagid)    -- ... news items tagged with ...
  JOIN news_tags AS n1 USING (newsid)   -- ... tagid = 16 and ...
  JOIN news_tags AS n2 USING (newsid)   -- ... tagid = 32
WHERE
  n1.tagid = 16 AND n2.tagid = 32
  AND tags.tagid NOT IN (16,32)         -- not the tags we already know about
ORDER BY tags.level, tags.tagid
于 2012-04-30T17:33:28.447 回答
1

编辑:我的查询严格基于提供的 sql OP,只是想按照问题标题中的要求加快查询速度。

SELECT DISTINCT t.tagid, t.tag FROM tags AS t
JOIN            news_tags AS nt1 USING (tagid) 
JOIN            news_tags AS nt2 USING (newsid)
WHERE           nt2.tagid IN (16, 32) AND t.tagid NOT IN (16, 32) 
GROUP BY        nt2.newsid HAVING COUNT(nt2.newsid)>=2
ORDER BY        t.level, t.tagid
于 2012-04-30T18:06:28.780 回答
0

我最终提出了一个快速查询,使用 JOINS 而不是 IN 语句解决了这个问题:

SELECT tags.tagid,tags.tag FROM tags 
INNER JOIN (SELECT DISTINCT news_tags.tagid FROM news_tags
INNER JOIN (SELECT newsid FROM news_tags WHERE tagid IN (16,32) 
GROUP BY newsid HAVING count(newsid) >= 2) tagged_news 
ON news_tags.newsid = tagged_news.newsid 
WHERE news_tags.tagid NOT IN (16,32)) rem_tags
ON tags.tagid = rem_tags.tagid
ORDER BY level, tagid

这显然不像 eggyal 的解决方案那样干净或优雅,所以我最终在我的应用程序中采用了他的解决方案。

我很想听听更多客观原因(除了优雅),为什么 eggyval 的解决方案优于上述 SQL 语句,既可以找到解决问题的最佳 SQL 语句,也可以为未来学习。感谢到目前为止的所有帮助。

于 2012-05-01T10:34:54.130 回答