MySQL计算当前连续日期的连续日期

Posted

技术标签:

【中文标题】MySQL计算当前连续日期的连续日期【英文标题】:MySQL count consecutive dates for current streak 【发布时间】:2014-08-12 19:03:29 【问题描述】:

给定一个包含 timestampuser 列的 mysql 表,我希望能够计算给定用户连续存在多少天(必须以今天结束)记录。

***/google 上的所有示例都涉及查找以前的条纹或计算总条纹,但我需要了解他们的当前条纹;

我可以使用它来查找有前一天记录的所有日期:

select date(start_of_votes.date_created)
from votes start_of_votes
left join votes previous_day
    on start_of_votes.username = previous_day.username
    and date(start_of_votes.date_created) - interval 1 day = date(previous_day.date_created)
where previous_day.id is not null
and start_of_votes.username = "bob"
group by date(start_of_votes.date_created) desc

但我只需要计算包含今天记录的范围。

根据请求,一些示例数据:

bob 2014-08-10 00:35:22
sue 2014-08-10 00:35:22
bob 2014-08-11 00:35:22
mike 2014-08-11 00:35:22
bob 2014-08-12 00:35:22
mike 2014-08-12 00:35:22

今天是 2014 年 8 月 12 日:

bob 连续 3 天 sue 没有当前的连续性 mike 连续 2 天

此数据是针对每个用户的,因此我将对bob 运行查询并得到3 作为结果。我不需要按用户细分的结果。

【问题讨论】:

您不能只使用用户变量 + 1 保持运行总计,然后将结果限制在当天给您“连续天数”吗? 能补充一些相关数据吗? 添加了一些示例数据 @xQbert 如果我可以“只是”做某事,我就不会问了。如果我错过了一些对我来说应该很明显的超级基础知识,那这不是第一次。 我的尝试是提供一个方向而不是精确的语法。对我来说,问题是缺少逻辑和功能知识,而不是语法错误,因此为什么我提供了方向而不是具体的解决方案....但是既然您似乎想要更多...请参阅下面的回复。 【参考方案1】:

查询将连续计数保存在一个变量中,一旦出现间隙,它就会将计数重置为一个较大的负数。然后它返回最大的连续。

根据用户可以拥有的投票数,您可能需要将-99999 更改为更大的(负)值。

select if(max(maxcount) < 0, 0, max(maxcount)) streak
from (
select 
  if(datediff(@prevDate, datecreated) = 1, @count := @count + 1, @count := -99999) maxcount,
  @prevDate := datecreated
  from votes v cross join 
    (select @prevDate := date(curdate() + INTERVAL 1 day), @count := 0) t1
  where username = 'bob'
  and datecreated <= curdate()
  order by datecreated desc
) t1;

http://sqlfiddle.com/#!2/37129/6

更新

另一种变化

select * from (
select datecreated, 
  @streak := @streak+1 streak, 
  datediff(curdate(),datecreated) diff
from votes 
cross join (select @streak := -1) t1
where username = 'bob'
and datecreated <= curdate()
order by datecreated desc
) t1 where streak = diff
order by streak desc limit 1

http://sqlfiddle.com/#!2/c6dd5b/20

请注意,fiddle 只有在本文发布之日运行时才会返回正确的条纹 :)

更新 2

下面的查询适用于允许同一用户每天进行多次投票的表格,方法是从删除重复日期的派生表格中进行选择。

select * from (
  select date_created, 
  @streak := @streak+1 streak, 
  datediff(curdate(),date_created) diff
  from (
    select distinct date(date_created) date_created
    from votes where username = 'pinkpopcold'
  ) t1
  cross join (select @streak := -1) t2
  order by date_created desc
  ) 
t1 where streak = diff
order by streak desc limit 1

http://sqlfiddle.com/#!2/5fc6d/7

您可能希望将select * 替换为select streak + 1,具体取决于您是否要将第一个投票包括在连续投票中。

【讨论】:

我无法让其中任何一个工作。例如,我有一个用户“dolly”,他今天和两天前投票,但昨天没有投票。它显示“连续 2,差异 2”,并且过去四天投票的用户,它显示没有连续。 @helion3 我用相同的场景创建了一个小提琴,它对我有用。也许您的数据库的 curdate() 不是您所期望的? sqlfiddle.com/#!2/d8716/1 这是一个示例用户:sqlfiddle.com/#!2/5fc6d/1/0。运行这个查询我得到:2014-08-17 08:18:03 - 1 - 1。服务器的curdate() 当前为2014-08-18 @helion3,我曾假设每个用户每天只能投 1 票。查看更新 @FuzzyTree 嘿伙计。我真的很喜欢您使用select streak + 1 进行的第二次更新。就我而言,我尝试计算 curdate() 发生了多少票但我失败了:(我尝试在不同的地方添加 COUNT 但这个查询对我来说太复杂了。有什么建议吗?【参考方案2】:

这是它的基本要点:

使用您开始使用的查询创建按日期排序的集合,然后用运行总计包装它以获取计数,但将结果限制在今天。我从内部查询中删除了用户名,以便在需要时可以将其应用于外部查询,或者返回今天匹配的一整套每个人。请注意,除非调整样本数据,否则此小提琴仅在 2014 年 8 月 12 日返回结果。

http://sqlfiddle.com/#!2/a8554/21/0

使用:

Create table votes (
id int,
date_created date,
username varchar(10));

insert into votes (id, username,date_created) VALUES
(1, 'bob', '2014-08-10 00:35:22'),
(2, 'sue', '2014-08-10 00:35:22'),
(3, 'bob', '2014-08-11 00:35:22'),
(4, 'mike', '2014-08-11 00:35:22'),
(5, 'bob', '2014-08-12 00:35:22'),
(6, 'mike', '2014-08-12 00:35:22');

然后

SET @runtot:=0;

select SOVUN, SOVDC, 
  case when SOVUN = PDUN
  then @runtot:=@runtot+1
  else @runtot:=0 end as RunningTotal
FROM (

SELECT 
start_of_Votes.username SOVUN, 
Start_of_Votes.Date_Created SOVDC, 
previous_day.username PDUN,
Previous_day.date_created PDDC
from votes start_of_votes
left join votes previous_day
    on start_of_votes.username = previous_day.username
    and date(start_of_votes.date_created) - interval 1 day = date(previous_day.date_created)
order by SOVUN, SOVDC) B

返回:

SOVUN   SOVDC                           RUNNINGTOTAL
bob     August, 10 2014 00:00:00+0000   0
bob     August, 11 2014 00:00:00+0000   1
bob     August, 12 2014 00:00:00+0000   2
mike    August, 11 2014 00:00:00+0000   0
mike    August, 12 2014 00:00:00+0000   1
sue     August, 10 2014 00:00:00+0000   0

请注意,如果不将其包装在子查询中,则不能按天限制,否则运行总数将不起作用。您不能更早地应用运行总计数,因为必须首先订购该集合。因此需要两个嵌套的子查询。

【讨论】:

我没有看到查询将结果限制为包括今天在内的条纹?通过我对真实数据的测试,它显示了每个用户的每条投票记录以及运行总数(就像你的前任一样,这很好,我可以自己统计它们),但计数真的很混乱。我想这是我的错,我忘了提到一个用户一天最多可能有六票。该查询根据当天的投票数计算每张选票,因此如果某人每天有 6 张选票,则将全部计算 6 次,每次 6 次。在为期一周的连续运行结束时,一位用户的总运行次数为 132。

以上是关于MySQL计算当前连续日期的连续日期的主要内容,如果未能解决你的问题,请参考以下文章

MySQL:从日期时间列计算连续工作日数

您如何计算 Microsoft Access SQL 查询中的连续日期?

sql 连续活跃天数

hutool日期工具类相关:获取某月所有周某周的起止时间或所有日期计算连续天数

计算连续日期 R

sql mysql