简体   繁体   中英

use mysql to calculate an unbroken streak, by date, after any three day break

I have a database table where I track people using my app. There might be multiple uses per user, per day. So an example recordset for a given single user might look like:

userId  dateOfUsage
1       2012-12-01
1       2012-12-02
1       2012-12-02
1       2012-12-03
1       2012-12-06
1       2012-12-07
1       2012-12-07
1       2012-12-08

Let's say today is 2012-12-08. I want to get the number of days between today and the last record after three days or more of no entries. In the above example, there was a break between 2012-12-03 and 2012-12-06, so I would like to count the days between 2012-12-06 and today (2012-12-08). The answer would be a "3 day streak" of the 6th to the 8th.

Is it possible to do this in MySQL only? How can I do this for a given user in MySQL? Is it possible to do it for all users at once?

I've found other questions about streaks, but haven't had any luck adapting them to solve my request. Thanks!

You can use a stored procedure with cursors to create a temporary table.

Alternatively you could do something like

set @dateOfUsage = NULL;
SELECT * FROM (
  SELECT IF(@dateOfUsage IS NULL, 0, datediff(dateOfUsage, @dateOfUsage)) as gap, @dateOfUsage:=dateOfUsage AS dateOfUsage FROM (
    SELECT * FROM `usage` WHERE userID = 1 ORDER BY dateOfUsage
  ) `usage`
) `t` WHERE gap >= 3;

http://sqlfiddle.com/#!2/22228/2

Note that you need to use a subquery because the order of the rows in a table is not guarantied.

I needed another subquery to filter (though I don't userstand why HAVING doesn't would).

Filter on user if you like...

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table 
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,userId  INT NOT NULL
,dateOfUsage DATE NOT NULL
);

INSERT INTO my_table (userid,dateofusage) VALUES
(1       ,'2012-12-01'),
(1       ,'2012-12-02'),
(1       ,'2012-12-02'),
(1       ,'2012-12-03'),
(2       ,'2012-12-04'),
(2       ,'2012-12-05'),
(1       ,'2012-12-06'),
(1       ,'2012-12-07'),
(1       ,'2012-12-07'),
(1       ,'2012-12-08');

SELECT DATEDIFF('2012-12-08',MAX(b.dateofusage))+1 streak  
  FROM ( SELECT x.*, COUNT(*) rank FROM my_table x JOIN my_table y ON y.userid = x.userid AND y.id <= x.id GROUP BY x.id) a
  JOIN ( SELECT x.*, COUNT(*) rank FROM my_table x JOIN my_table y ON y.userid = x.userid AND y.id <= x.id GROUP BY x.id) b
    ON b.dateofusage >= a.dateofusage + INTERVAL 3 DAY
   AND b.rank = a.rank + 1
   AND b.userid = a.userid
 GROUP
    BY a.userid;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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