在 MySQL 中实现“连续天数计算”或者“连续登录天数统计”并不直接,但可以通过 日期差值技巧 + 分组统计的方法来完成。下面是详细教程,包括原理 + 示例 + SQL 写法:


🧠 原理讲解:连续日期的分组技巧

假设你有如下登录记录表:

CREATE TABLE user_login (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT,
    login_date DATE
);

示例数据:

user_idlogin_date
12025-08-01
12025-08-02
12025-08-03
12025-08-05
12025-08-06
12025-08-07

✅ 目标:找出用户每段连续登录的时间段和连续天数


📌 核心思想:

连续日期与“行号 – 日期差值”具有线性关系

DATEDIFF(login_date, ROW_NUMBER) = 固定值

所以我们可以通过以下方式实现分组。


🧪 示例 SQL(MySQL 8+ 支持窗口函数)

WITH ranked_logins AS (
  SELECT
    user_id,
    login_date,
    ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_date) AS rn
  FROM user_login
),
grouped_logins AS (
  SELECT
    user_id,
    login_date,
    DATE_SUB(login_date, INTERVAL rn DAY) AS grp_key
  FROM ranked_logins
)
SELECT
  user_id,
  MIN(login_date) AS start_date,
  MAX(login_date) AS end_date,
  COUNT(*) AS continuous_days
FROM grouped_logins
GROUP BY user_id, grp_key
ORDER BY user_id, start_date;

🧾 查询结果:

user_idstart_dateend_datecontinuous_days
12025-08-012025-08-033
12025-08-052025-08-073

📌 找最长连续登录天数

在上面的 grouped_logins 基础上再包一层:

WITH ... -- 同上
SELECT
  user_id,
  MAX(continuous_days) AS max_continuous_days
FROM (
  SELECT
    user_id,
    DATE_SUB(login_date, INTERVAL rn DAY) AS grp_key,
    COUNT(*) AS continuous_days
  FROM ranked_logins
  GROUP BY user_id, grp_key
) AS t
GROUP BY user_id;

🧠 说明:

  • ROW_NUMBER():给每个用户登录记录按日期编号
  • login_date - row_number:连续日期的这个值是一样的(等差)
  • DATE_SUB():生成“组键”来分组

❗ 如果你用的是 MySQL 5.x(不支持窗口函数)

需要使用变量实现 row_number()

SELECT 
    user_id, login_date,
    @rn := IF(@prev_user = user_id, @rn + 1, 1) AS rn,
    @prev_user := user_id
FROM 
    (SELECT * FROM user_login ORDER BY user_id, login_date) AS t,
    (SELECT @rn := 0, @prev_user := NULL) AS vars;

后续逻辑类似,但代码较复杂,如需我可以为你继续整理。


✅ 总结

目标方法
连续登录时间段统计ROW_NUMBER + DATE_SUB 分组
最长连续登录天数上面结果上再聚合 MAX()
不支持窗口函数时的替代方案使用变量模拟 row_number
按用户分组统计连续登录PARTITION BY user_id 实现

好的,下面我来为你提供一个完整的 MySQL 解决方案,用于 统计每个用户的连续登录天数段落,并找出每个用户的 最长连续登录天数


🧩 一、假设表结构如下:

CREATE TABLE user_login (
  id INT AUTO_INCREMENT PRIMARY KEY,
  user_id INT NOT NULL,
  login_date DATE NOT NULL
);

🧪 示例数据:

INSERT INTO user_login (user_id, login_date) VALUES
(1, '2025-08-01'),
(1, '2025-08-02'),
(1, '2025-08-03'),
(1, '2025-08-05'),
(1, '2025-08-06'),
(1, '2025-08-07'),
(2, '2025-08-01'),
(2, '2025-08-03'),
(2, '2025-08-04'),
(2, '2025-08-05');

✅ 二、统计连续登录的时间段(MySQL 8+ 版本)

WITH ranked AS (
  SELECT
    user_id,
    login_date,
    ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_date) AS rn
  FROM user_login
),
grouped AS (
  SELECT
    user_id,
    login_date,
    DATE_SUB(login_date, INTERVAL rn DAY) AS grp_key
  FROM ranked
)
SELECT
  user_id,
  MIN(login_date) AS start_date,
  MAX(login_date) AS end_date,
  COUNT(*) AS continuous_days
FROM grouped
GROUP BY user_id, grp_key
ORDER BY user_id, start_date;

🥇 三、统计每个用户最长连续登录天数

WITH ranked AS (
  SELECT
    user_id,
    login_date,
    ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY login_date) AS rn
  FROM user_login
),
grouped AS (
  SELECT
    user_id,
    DATE_SUB(login_date, INTERVAL rn DAY) AS grp_key
  FROM ranked
)
SELECT
  user_id,
  MAX(continuous_days) AS max_continuous_days
FROM (
  SELECT
    user_id,
    grp_key,
    COUNT(*) AS continuous_days
  FROM grouped
  GROUP BY user_id, grp_key
) AS t
GROUP BY user_id;

✅ 四、查询结果(示意)

user_idstart_dateend_datecontinuous_days
12025-08-012025-08-033
12025-08-052025-08-073
22025-08-012025-08-011
22025-08-032025-08-053
user_idmax_continuous_days
13
23

🛠 五、MySQL 5.x 兼容方案(无窗口函数)

如果你数据库版本低于 8.0,不支持 ROW_NUMBER(),我可以提供带变量的方案(较复杂),可以继续给我说“我用的是 MySQL 5.7”等,我会按老版本适配。