0

我昨天问了这个问题,但我似乎没有说得足够清楚,所以我要添加一些信息以使一切清楚。

考虑以下 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 点之后,他没有再次输入, counter 将设置为 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;

但是,到目前为止我还没有介绍userID,最大的问题是:它只需要最后一个连胜,无论到今天是否有差距。但是,如前所述,它总是以今天为参考。

我希望有人可以在这里帮助我。

最后一个重要信息:我使用的是 MariaDB 10.1.45,因此“WITH”或“ROWNUM()”不可用,目前无法更新。

提前致谢!

4

1 回答 1

0

在使用窗口函数的更新版本中,这确实会更简单。但是您可以调整变量以获得用户的所有条纹:

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 byandorder 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您可以在外部查询中使用 a 将它们放回原处。但是,您确实需要一个包含所有用户的表,而不是您的两个单独的表,所以我没有打扰。

于 2020-08-08T12:20:46.367 回答