您忘记了为每行设置@prevDate
,并且返回的是最大条纹而不是最新条纹.
如果您使用的是MySQL&>=8.0,则可以使用window functions,而不是deprecated setting of user variables in expressions:
WITH streaks AS (
SELECT
habit_id,
DATE(created_at) AS dt,
DATE(created_at) - INTERVAL DENSE_RANK() OVER (PARTITION BY habit_id ORDER BY DATE(created_at) ASC) DAY AS grp
FROM habit_progress_logs
WHERE habit_id = 4
),
streaks2 AS (
SELECT
habit_id,
grp,
COUNT(DISTINCT dt) AS length,
ROW_NUMBER() OVER (PARTITION BY habit_id ORDER BY grp DESC) AS rn
FROM streaks
GROUP BY habit_id, grp
)
SELECT habit_id, length AS currentStreak
FROM streaks2
WHERE rn = 1;
前CTE个给出了日期序列分组,使用DENSE_RANK()(添加rnk
用于说明):
habit_id |
dt |
rnk |
grp |
4 |
2023-07-14 |
1 |
2023-07-13 |
4 |
2023-07-15 |
2 |
2023-07-13 |
4 |
2023-07-16 |
3 |
2023-07-13 |
4 |
2023-07-17 |
4 |
2023-07-13 |
4 |
2023-07-19 |
5 |
2023-07-14 |
4 |
2023-08-20 |
6 |
2023-08-14 |
4 |
2023-08-21 |
7 |
2023-08-14 |
4 |
2023-08-23 |
8 |
2023-08-15 |
4 |
2023-08-24 |
9 |
2023-08-15 |
4 |
2023-08-25 |
10 |
2023-08-15 |
4 |
2023-08-26 |
11 |
2023-08-15 |
4 |
2023-08-27 |
12 |
2023-08-15 |
4 |
2023-08-28 |
13 |
2023-08-15 |
4 |
2023-09-13 |
14 |
2023-08-30 |
4 |
2023-09-14 |
15 |
2023-08-30 |
4 |
2023-09-15 |
16 |
2023-08-30 |
4 |
2023-09-15 |
16 |
2023-08-30 |
4 |
2023-09-16 |
17 |
2023-08-30 |
4 |
2023-09-17 |
18 |
2023-08-30 |
第二个CTE进行分组,并添加ROW_NUMBER():
habit_id |
grp |
length |
rn |
4 |
2023-08-30 |
5 |
1 |
4 |
2023-08-15 |
6 |
2 |
4 |
2023-08-14 |
2 |
3 |
4 |
2023-07-14 |
1 |
4 |
4 |
2023-07-13 |
4 |
5 |
如果您在使用MySQL<;8.0时遇到困难:
SELECT habit_id, COUNT(*) AS currentStreak
FROM (
SELECT
habit_id,
dt,
@grp := IF(@prevHabitId = habit_id AND dt = @prevDate + INTERVAL 1 DAY, @grp, @grp + 1) AS grp,
@prevDate := dt,
@prevHabitId := habit_id
FROM (
SELECT habit_id, DATE(created_at) AS dt
FROM habit_progress_logs
JOIN (SELECT @prevHabitId := NULL, @prevDate := NULL, @grp := 0) i
WHERE habit_id = 4
GROUP BY habit_id, dt
ORDER BY habit_id, dt
) s
) t1
GROUP BY habit_id, grp
ORDER BY habit_id, grp DESC
LIMIT 1;
这是一张db<>fiddle