mysql/mariadb 中的数据库条目连续记录 - 直到今天
Posted
技术标签:
【中文标题】mysql/mariadb 中的数据库条目连续记录 - 直到今天【英文标题】:Database entry streak in mysql/mariadb - until today 【发布时间】:2020-08-08 07:10:45 【问题描述】:我昨天问了这个问题,但我似乎并没有说得足够清楚,所以我要添加一些信息以使一切清楚。
考虑以下 2 个表格:
0_12_table
ID userID text timestamp
1 1 bla 2020-08-07 10:30:00
2 1 blub 2020-08-06 11:30:00
3 1 abc 2020-08-05 09:20:00
4 1 def 2020-08-04 06:13:00
5 2 ghi 2020-08-02 08:05:00
6 2 abc 2020-08-05 10:20:00
7 3 def 2020-08-04 07:13:00
8 4 ghi 2020-08-02 09:05:00
9 5 jkl 2020-08-07 06:30:00
10 5 mno 2020-08-08 08:32:00
12_24_table:
ID userID text timestamp
1 1 bla 2020-08-07 19:30:00
2 1 blub 2020-08-06 21:30:00
3 1 abc 2020-08-05 19:20:00
4 2 def 2020-08-04 16:13:00
5 2 ghi 2020-08-02 18:05:00
6 2 abc 2020-08-05 20:20:00
7 3 def 2020-08-04 17:13:00
8 4 ghi 2020-08-02 19:05:00
9 5 jkl 2020-08-07 20:13:00
基本上,用户可以(并且很乐意这样做)在 00:00 到 12:00 之间以及在 12:01 到 23:59 之间在数据库中添加一个条目。
现在我想奖励他们添加连续条目。每当他们错过时间范围时,那个“计数器”就会重置为 0...
在上面给定的数据中,用户 ID 为 1 的用户现在连续 3 天(在我的时间,现在是上午 9 点),但只要在上午 12 点之后,他就没有再做一次条目,计数器将被设置为 0 并且连续结束,因为他错过了早上添加条目。
用户 ID 为 2,3 和 4 的用户根本不会出现连击。如果缺少一个早上或晚上的条目,则连续取消。
用户 ID 为 5 的用户在 12:01 到 23:59 的时间范围内每次进入时,连续 1 次都会增加到 2 次。
我希望你明白其中的逻辑。重要的是,如果他在 2 天前连续 10 次,这并不重要。每当有条目丢失时,连胜将重置为 0。因此,如果某天早上 12 点之前没有条目,或者晚上 23:59 之前没有条目,那么连胜就消失了。它总是使用今天作为参考,因此它确实是“直到今天的连续条目”。
到目前为止,我得到的答案似乎很接近:
select min(dte), max(dte), count(*)
from (select dte, (@rn := @rn + 1) as seqnum
from (select dte
from ((select date(timestamp) as dte, 1 as morning, 0 as evening
from morning
) union all
(select date(timestamp) as dte, 0 as morning, 1 as evening
from evening
)
) me
group by dte
having sum(morning) > 0 and sum(evening) > 0
order by dte
) d cross join
(select @rn := 0) params
) me
group by dte - interval seqnum day
order by count(*) desc
limit 1;
但是,到目前为止我还没有介绍用户ID,最大的问题是:它只需要最后一个连胜,无论到今天是否有差距。但是,如前所述,它总是以今天为参考。
我希望有人可以在这里帮助我。
最后的重要信息:我使用的是 MariaDB 10.1.45,因此“WITH”或“ROWNUM()”不可用,目前无法更新。
提前致谢!
【问题讨论】:
【参考方案1】:在使用窗口函数的较新版本中,这确实会更简单。但是您可以调整变量以获得用户的所有条条纹:
select userid, count(*) as length
from (select dte, (@rn := @rn + 1) as seqnum
from (select dte
from ((select userid, date(timestamp) as dte, 1 as morning, 0 as evening
from morning
) union all
(select userid, date(timestamp) as dte, 0 as morning, 1 as evening
from evening
)
) me
group by userid, dte
having sum(morning) > 0 and sum(evening) > 0
order by userid, dte
) d cross join
(select @rn := 0) params
) me
group by userid, dte - interval seqnum day
order by count(*) desc;
事实证明,对于这个问题,“全局”序列和局部序列一样有效,因此变量的使用仍然很简单。更改的是 group by
和 order by
子句。
然后您可以将其用作子查询来获取最大值:
select userid, max(seq)
from (select userid, count(*) as seq
from (select dte, (@rn := @rn + 1) as seqnum
from (select dte
from ((select userid, date(timestamp) as dte, 1 as morning, 0 as evening
from morning
) union all
(select userid, date(timestamp) as dte, 0 as morning, 1 as evening
from evening
)
) me
group by userid, dte
having sum(morning) > 0 and sum(evening) > 0
order by userid, dte
) d cross join
(select @rn := 0) params
) me
group by userid, dte - interval seqnum day
) u
group by userid;
注意:没有条纹的用户将被过滤掉。您可以在外部查询中使用left join
将它们放回原处。但是,您确实需要一个包含所有 用户 的表,而不是您的两个单独的表,所以我没有打扰。
【讨论】:
嘿,谢谢你的回答.. 不幸的是,结果仍然不正确......我用我的表试了一下,结果是 2,它应该是 0,因为用户没有最后一天添加一个条目...还在select语句中添加了几次userid
看到这个小提琴:dbfiddle.uk/… 并将其与我上面的描述进行比较......即使没有条目,用户仍然有连续性......
另外,当做一些改变时,它会做一些奇怪的事情,在这种情况下,userID 2 在结果中有 2 次出现:dbfiddle.uk/…以上是关于mysql/mariadb 中的数据库条目连续记录 - 直到今天的主要内容,如果未能解决你的问题,请参考以下文章