SQL连接,Count()和group by按'是/否'投票'排序'帖子'

时间:2009-11-18 20:37:22

标签: sql mysql join count

我有postsvotescomments个表格。每个帖子都可以有N'是投票',N'无投票'和N条评论。我试图获得一组按照投票数排序的帖子。

我有一个查询正是这样做,但运行得太慢了。在1500个帖子和15K票的数据集上,我的开发机器需要0.48秒。我该如何优化呢?

select
  p.*,
  v.yes,
  x.no
from
  posts p
left join (select post_id, vote_type_id, count(1) as yes from votes where (vote_type_id = 1) group by post_id) v on v.post_id = p.id
left join (select post_id, vote_type_id, count(1) as no from votes where (vote_type_id = 2) group by post_id) x on x.post_id = p.id
left join (select post_id, count(1) as comment_count from comments group by post_id) p on p.confession_id = p.id
order by
  yes desc
limit
    0, 10

修改

  • VotesComments都有post_id FK
  • vote_type_id表中的post_idvotes上添加索引,使查询执行中的.1sec无效。

4 个答案:

答案 0 :(得分:0)

添加'yes_count'列并使用触发器在投票时更新每个帖子的投票计数。您可以索引此列,然后它应该非常快。

答案 1 :(得分:0)

使用explain检查查询执行计划,以便了解它为什么会变慢,通常只需查看计划并稍后创建适当的索引就足够了。 1.5k和15k表非常小,因此查询速度要快得多。

答案 2 :(得分:0)

为什么不添加列是和否?不是在每个帖子上添加新条目,只需增加计数。

如果我误解了你的数据库或你无法修改它,至少你有一个外键在votes.post_id到post.id?如果你做任何加入,外键是非常重要的。

答案 3 :(得分:0)

首先,您当前的查询不应该编译,因为它使用p作为注释和posts表的别名。

其次,你加入votes两次:一次是否,一次是肯定。使用CASE语句,您可以使用单个连接计算两者的总和。这是一个示例查询:

select
  p.*,
  sum(case when v.vote_type_id = 1 then 1 else 0 end) as yes,
  sum(case when v.vote_type_id = 2 then 1 else 0 end) as no,
  count(c.id) as comment_count
from posts p
left join votes v on v.post_id = p.id
left join comments c on c.post_id = p.id
order by yes desc
limit 0, 10

第三,您可以验证帖子,投票和评论之间的关系是否存在正确的外键。 (post_id, vote_type_id)上的votes索引也可以提供帮助。