MySQL计算当前连续日期的连续日期
Posted
技术标签:
【中文标题】MySQL计算当前连续日期的连续日期【英文标题】:MySQL count consecutive dates for current streak 【发布时间】:2014-08-12 19:03:29 【问题描述】:给定一个包含 timestamp
和 user
列的 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计算当前连续日期的连续日期的主要内容,如果未能解决你的问题,请参考以下文章
您如何计算 Microsoft Access SQL 查询中的连续日期?