【问题标题】:MySQL order by count for last hour recursiveMySQL按最后一小时递归的计数排序
【发布时间】:2013-07-04 15:36:42
【问题描述】:

我有一个 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 中进行这种递归排序,或者我们必须在代码中手动解决这个问题?欢迎所有想法。请注意,性能在这里很重要,因为整个网站都在使用顶部列表。

【问题讨论】:

  • 您如何将给定视频的短信投票和投票时间存储在其他表中?换句话说,添加查询,该查询将给出给定视频在给定小时内的 SMS 投票数。
  • 是的。还有2张桌子,一张短信投票,一张脸书投票

标签: mysql sql datetime sql-order-by


【解决方案1】:

我认为使用递归计算执行这种排序是不可行的(这可能是无限的),但如果你愿意限制回顾的时间,有一些方法可以做到.

这是一种可能性。

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 字段和一个 time 字段。

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

将其扩展为包含更广泛的时间范围相当容易,但您可能还想考虑在时间倒退时使用增加的时间范围。例如,您首先查看过去一小时内的投票,然后是过去一天,然后是过去一周等。我怀疑这会降低您获得相同投票的视频的机会,而无需添加尽可能多的额外计算。

SQL Fiddle example

【讨论】:

  • 这很简单,但遗憾的是不可接受。我们不能把它限制在几个间隔内
猜你喜欢
  • 2016-01-08
  • 2011-01-04
  • 2012-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-03
  • 2020-07-30
相关资源
最近更新 更多