简体   繁体   English

MySQL最近n天连续事件的另一个计数/等级

[英]Yet another count/rank for consecutive events in the last 'n' days in MySQL

I'm having trouble in to setup a query to count/rank the consecutive days an event had happened in the last ' n ' days. 我在设置查询以对最近' n '天内事件发生的连续天数进行计数/排名时遇到了麻烦。 Ie: If an event had happened consecutively ' k ' times in the last ' n ' days, with no gaps in relation to the reference date. 即:如果某事件在过去的' n '天连续发生了' k '次,与参考日期之间没有任何间隔。

Visually (0 means no event, and 1 means an event) from current date to the past ' n ' days: 从当前日期到过去' n '天的外观(0表示没有事件,1表示事件):

case A - 01111 (count as 0 since there's no event in the previous date).
case B - 11001 (count as 2 consecutive days)
case C - 11110 (count as 4 consecutive days)
case D - 00110 (also count as 0)
case E - 10111 (count as 1)... and so on

Considering a 'pseudo' structure: 考虑“伪”结构:

Table1
uid
eventid

table2
eventid
datetime

What I need as result is a 'rank' of uid wich has consecutive events in the last n days so if I got these values on Table1 and Table2: 结果,我需要的是uid的“等级”,在过去n天中有连续的事件,因此,如果我在Table1和Table2上获得了这些值:

Table1
(1, 100)
(1, 101)
(1, 102)
(1, 103)
(2, 104)
(2, 105)
(2, 106)

Table2
(100, '2015-09-11 00:00:00')
(101, '2015-09-10 00:00:00')
(102, '2015-09-09 00:00:00')
(103, '2015-09-07 00:00:00')
(104, '2015-09-11 00:00:00')
(105, '2015-09-10 00:00:00')
(106, '2015-09-05 00:00:00')

The result shoud be: 结果应该是:

uid - consecutive
1 - 3
2 - 2

That means uid 1 has events 100, 101, and 102 consecutively in the last days but eventid 103 is out because it is not consecutive. 这意味着uid 1在最后几天连续发生事件100、101和102,但是eventid 103退出,因为它不连续。

I've looking for similar questions and tried to apply some of them, but none consider the consecutive days based on a reference (current) date. 我正在寻找类似的问题,并尝试应用其中的一些问题,但是没有人考虑基于参考(当前)日期的连续几天。

The near I've come is to make a left join using the date for each case something similar to: 我即将来临的是使用每种情况的日期进行左联接,类似于:

SELECT * FROM
(SELECT * FROM Table1 LEFT JOIN Table2 USING (uid) WHERE date(datetime)=curdate()-interval 3 day) 
LEFT JOIN (SELECT * FROM Table1 LEFT JOIN Table2 USING (uid) WHERE date(datetime)=curdate()-interval 2 day)
LEFT JOIN (SELECT * FROM Table1 LEFT JOIN Table2 USING (uid) WHERE date(datetime)=curdate()-interval 1 day)

Also my knowledge in using var inside SQL are almost none, and if possible I'd like to avoid using procedures, making a single call from inside php to mysql. 另外,我在SQL内部使用var的知识几乎没有,如果可能的话,我想避免使用过程,而是从php内部向mysql进行一次调用。

Thx 谢谢

You can use a counter variable to do just that. 您可以使用计数器变量来做到这一点。

First we'll get a table with uid and datetime columns, ordered properly: 首先,我们将获得一个包含uiddatetime列的表,并按正确的顺序排列:

SELECT `uid`,`datetime` FROM `table1`
INNER JOIN `table2` ON `table1`.`eventid`=`table2`.`eventid`
ORDER BY `uid`, `datetime`

Now we'll use that as a subquery, advancing a counter each time the uid is the same as last row, and the datetime is 1 day ahead of the last row's date. 现在,我们将其用作子查询,每次uid与最后一行相同时,都会前进一个计数器,并且datetime比最后一行的日期早1天。 Here's how it's done: 这是完成的过程:

SET @counter = 1;
SET @lastDate = '2010-01-01 00:00:00';
set @lastUid = 0;

SELECT
  `uid`,
  IF (((DATE_ADD(@lastDate, INTERVAL 1 DAY)=`datetime`) AND (`uid`=@lastUid)),
    @counter := @counter+1, @counter := 1),
  (@lastUid := `uid`),
  (@lastDate := `datetime`),
  @counter as `counter`
FROM (
  SELECT `uid`,`datetime` FROM `table1`
  INNER JOIN `table2` ON `table1`.`eventid`=`table2`.`eventid`
  ORDER BY `uid`, `datetime` ASC
  ) `uidDateTable`

Now all we have left to do is to use that query as a subquery and find the MAX value of counter per uid . 现在剩下要做的就是将该查询用作子查询,并为每个uid找到counterMAX值。 So that's the actual query you need: 这就是您需要的实际查询:

SET @counter = 1;
SET @lastDate = '2010-01-01 00:00:00';
set @lastUid = 0;

SELECT `uid`, max(`counter`)
FROM (
  SELECT
    `uid`,
    IF (((DATE_ADD(@lastDate, INTERVAL 1 DAY)=`datetime`) AND (`uid`=@lastUid)),
      @counter := @counter+1, @counter := 1),
    (@lastUid := `uid`),
    (@lastDate := `datetime`),
    @counter as `counter`
  FROM (
    SELECT `uid`,`datetime` FROM `table1`
    INNER JOIN `table2` ON `table1`.`eventid`=`table2`.`eventid`
    ORDER BY `uid`, `datetime` ASC
    ) `uidDateTable`
  ) `uidCounters`
GROUP BY `uid`;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM