MySQL按顺序递归递归最后一小时

时间:2013-07-04 15:36:42

标签: mysql sql datetime sql-order-by

我有一个SQL问题。首先,我想知道只有SQL才有可能,如果没有,有人知道一个好的解决方法。

我们正在建立一个网站,用户可以在该网站上投票支持视频 用户可以在Facebook身份验证后通过短信或直接在网站上投票 我们必须列出所有视频的最高列表,并计算每个视频列表的“位置”。

到目前为止,我们已经使用一个简单的子查询来做到这一点,如下所示:

SELECT v.video_id AS id, 
    (SELECT (COUNT(*)+1) FROM videos AS v2 
        WHERE (v2.SMS_votes + v2.facebook_votes) > (v.SMS_votes + v.facebook_votes)) AS total_position 
FROM videos AS v

SMS_votesfacebook_votes是汇总字段。每种投票都有单独的表格,每张投票都有记录,包括投票时间。

这很好用,计算位置......如果两个或多个视频的票数相同,他们会“分享”这个位置。

不幸的是,没有位置共享,我们必须通过以下规则解决它:

  • 如果2个视频的票数相同,那么拥有更多短信票数的视频就具有优势
  • 如果他们也拥有相同数量的短信投票,那么在过去一小时内拥有更多短信投票的人有优势
  • 如果他们在过去一小时内也有相同数量的短信投票,他们会按照之前的小时进行比较,并递归地比较,直到两者之间存在差异

是否可以仅在SQL中执行此类递归排序,还是必须在代码中手动解决此问题?欢迎所有想法。需要注意的是,性能在这里很重要,因为顶部列表在整个站点中使用。

1 个答案:

答案 0 :(得分:0)

我认为通过重复计算(可能无限制)执行此类排序是不可行的,但如果您愿意限制回顾的时间,可以采取一些方法

这是一种可能性。

SELECT video_id,
  SMS_votes + facebook_votes AS total_votes,
  SMS_votes,
  COUNT(CASE WHEN time > NOW() - INTERVAL 1 HOUR THEN 1 END) AS h1,
  COUNT(CASE WHEN time > NOW() - INTERVAL 2 HOUR THEN 1 END) AS h2,
  COUNT(CASE WHEN time > NOW() - INTERVAL 3 HOUR THEN 1 END) AS h3
FROM videos
JOIN SMS_votes USING(video_id)
GROUP BY video_id
ORDER BY total_votes DESC, SMS_votes DESC, h1 DESC, h2 DESC, h3 DESC;

这假设您有一个名为 SMS_votes 的表格跟踪每个投票,并带有 video_id 字段和时间字段。

对于每个视频,它计算总票数,短信投票,过去一小时,过去两小时和过去三小时的短信投票。然后,它会对所有这些值执行ORDER BY以获得正确的位置。

将此扩展包含更广泛的小时数相当容易,但您可能还需要考虑使用越来越长的时间范围。例如,您首先查看过去一小时,过去一天,过去一周等的投票。我怀疑这会降低您拥有相同投票的视频的机会,而无需添加额外的计算。

SQL Fiddle example