統計用戶在指定時間範圍內的最大連續登錄天數。例:1/3、1/4 登錄 → 連續 2 天;1/6~1/10 每日登錄 → 最大連續 5 天。用戶量大、跨度長(如 2 年),應用層循環不可行,需下推到數據庫單條 SQL 完成。
MySQL 5.7/8.0 無原生 LAG/LEAD 窗口函數(8.0 有但舊版項目多),利用會話變量 @last_uid、@last_dt、@cont_day、@cont_ix 掃描有序數據,標記連續段分組編號。
SELECT uid, MAX(lianxu_days) AS max_consecutive_days,
MIN(start_date) AS period_start, MAX(end_date) AS period_end
FROM (
SELECT uid,
MAX(days) AS lianxu_days,
MIN(login_day) AS start_date,
MAX(login_day) AS end_date
FROM (
SELECT
uid,
@cont_day := CASE
WHEN @last_uid = uid AND DATEDIFF(created_ts, @last_dt) = 1 THEN @cont_day + 1
WHEN @last_uid = uid AND DATEDIFF(created_ts, @last_dt) < 1 THEN @cont_day -- 同天多次記錄不斷連續
ELSE 1
END AS days,
@cont_ix := @cont_ix + IF(@cont_day = 1, 1, 0) AS cont_ix, -- 新分組遞增
@last_uid := uid,
@last_dt := created_ts AS login_day
FROM (
SELECT uid, DATE(created_ts) AS created_ts
FROM plan_stage
WHERE uid != 0
ORDER BY uid, created_ts
) t,
(SELECT @last_uid := 0, @last_dt := NULL, @cont_ix := 0, @cont_day := 0) t1
) t2
GROUP BY uid, cont_ix
HAVING lianxu_days > 10 -- 可調整閾值
) tmp
GROUP BY uid
ORDER BY max_consecutive_days DESC;
| 變量 | 含義 | 更新規則 |
|---|---|---|
@last_uid | 上一行用戶 ID | 每行賦值 @last_uid := uid |
@last_dt | 上一行登錄日期 | 每行賦值 @last_dt := created_ts |
@cont_day | 當前連續天數計數器 | 同用戶且日期差 1 → +1;同用戶同天 → 不變;換用戶 → 1 |
@cont_ix | 連續分組編號 | @cont_day = 1 時 +1,標記新連續段起始 |
plan_stage(uid, created_ts) 覆蓋內層排序與分組WHERE created_ts BETWEEN '2016-01-01' AND '2016-12-31' 減少掃描行uid, created_tsLIMITWITH ranked AS (
SELECT
uid,
DATE(created_ts) AS login_day,
LAG(DATE(created_ts)) OVER (PARTITION BY uid ORDER BY DATE(created_ts)) AS prev_day
FROM plan_stage
WHERE uid != 0
),
grouped AS (
SELECT
uid,
login_day,
SUM(CASE WHEN DATEDIFF(login_day, prev_day) = 1 THEN 0 ELSE 1 END)
OVER (PARTITION BY uid ORDER BY login_day) AS grp
FROM ranked
)
SELECT uid, COUNT(*) AS consecutive_days
FROM grouped
GROUP BY uid, grp
ORDER BY consecutive_days DESC
LIMIT 10;
窗口函數可讀性強、無變量副作用,建議 8.0+ 專案優先採用。
利用會話變量單掃描完成連續段分組,是 MySQL 5.x 解決「最大連續登錄/簽到/活躍天數」類問題的經典模式。核心口訣:按用戶/時間排序 → 變量判斷連續 → 分組標記 → 聚合取最大。理解變量流轉邏輯,舉一反三解決連續庫存、連續交易等同構問題。