题
我甚至不确定这是否有效,但这是我的问题:
我正在编写一个基本上是博客引擎的博客文章和每个博客文章的所有回复都可以标记。
所以,我可以将博客文章标记为“堆叠”,并回复该帖子标记为“溢出”。
现在,当用户点击我的应用程序中的特殊页面时,我正在尝试生成最常用标签的列表。它不仅应该通过减少博客帖子的数量来返回n个最受欢迎的标签,还应该返回与每个标签关联的博客帖子的数量,即使该帖子中的回复而不是帖子本身也标记有该标签强>
因此,如果BlogPost A标记为“foo”,并且BlogPost B中的回复标记为“foo”,则流行标记摘要应该将其计为总共两个博客帖子,即使BlogPost B不是技术上标记。
以下是可能相关的表/字段的说明:
BlogPosts
| id # Primary key for all tables, Rails-style
BlogComments
| id
| blog_post_id
Tags
| id
| name # 'foo'
Taggings
| id
| tag_id
| blog_post_id
| blog_comment_id
为方便起见,Taggings中存在一些非规范化。如果某人标记了BlogPost,则会填写blog_post_id字段,而blog_comment_id仍为NULL。如果有人将评论标记为帖子,则会填写blog_post_id和blog_comment_id。
有没有办法在一个或多个SQL查询中返回最常用标签的排序列表?我想我可能需要在cron作业上每隔几分钟运行一个计算成本高的脚本并渲染缓存的输出,而不是每当有人点击页面时运行它...
谢谢!
解决方案
到目前为止,我发现您的请求中没有任何复杂内容:
SELECT
tag_id,
COUNT(blog_post_id) + COUNT(blog_comment_id) tag_count
FROM
Taggings
GROUP BY
tag_id
ORDER BY
COUNT(blog_post_id) + COUNT(blog_comment_id) DESC
如果您想要计算“受影响的博客帖子”只是,我认为就是这样:
SELECT
t.id tag_id,
t.name tag_name,
COUNT(DISTINCT COALESCE(x.blog_post_id, c.blog_post_id)) tag_count
FROM
Tags t
INNER JOIN Taggings x ON x.tag_id = t.id
LEFT JOIN BlogComments c ON c.id = x.blog_comment_id
GROUP BY
t.id,
t.name
ORDER BY
COUNT(DISTINCT COALESCE(x.blog_post_id, c.blog_post_id)) DESC
其他提示
我可能会遗漏一些显而易见的东西但是因为你有“如果某人将评论标记到帖子,它填写了blog_post_id和blog_comment_id”,则以下sql应该可以解决问题。 我在这里假设这里的Tags.name将是唯一的。
SELECT MIN(ts.tag_id), t.name, COUNT(ts.blog_post_id) as rank
FROM Taggings ts
INNER JOIN Tags t ON ts.tag_id = t.id
GROUP BY t.name
ORDER BY COUNT(ts.blog_post_id) DESC
希望这就是你要找的东西。
我没试过,但这样的事情怎么样?:
select t.Id,
t.Name,
count(*)
from Taggings tings
inner join Tags t
on (t.id = tings.blog_post_id or t.id = tings.blog_comment_id)
group by t.Id, t.Name
order by count(*) desc