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

时间:2014-08-12 19:03:29

标签: mysql sql

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

stackoverflow / 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作为结果。我不需要用户细分的结果。

2 个答案:

答案 0 :(得分:2)

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

根据用户可以拥有多少票数,您可能需要将-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

注意,如果在本帖发布之日运行,小提琴只会返回正确的条纹:)

更新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,具体取决于您是否要在连胜中加入第一个投票。

答案 1 :(得分:0)

以下是它的基本要点:

使用您开始使用的查询按日期创建有序集,然后使用运行总计将其换行以获取计数,但将结果限制为今天。我从内部查询中删除了用户名,以便在需要时将其应用于外部,或者返回当前匹配的每个人的整个集合。请注意,除非调整样本数据,否则此小提琴仅返回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

请注意,您可以在白天进行限制而不将其包装在子查询中,否则运行总计数将无效。您不能提前应用运行总计数,因为必须先订购该集。因此需要两个嵌套的子查询。