AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 76930264
Accepted
ALS
ALS
Asked: 2023-08-18 22:32:01 +0800 CST2023-08-18 22:32:01 +0800 CST 2023-08-18 22:32:01 +0800 CST

MySQL:获取连续记录的数量(日期)?

  • 772

需要获取用户连续完成一项习惯(连续)的天数。这意味着最近的连续记录(今天倒退),而不一定是最长的连续记录。

插入以下日期后,我预计 4

  • 2023-09-14
  • 2023-09-15
  • 2023-09-16
  • 2023-09-17

这个查询始终返回 1,我哪里出错了?

SELECT s.habit, MAX(s.streak) AS currentStreak
  FROM ( SELECT IF(@prev = o.habit_id AND o.date = @prevDate + INTERVAL 1 DAY
                  , @streak := @streak + 1
                  , @streak := 1
                ) AS streak
              , @prev := o.habit_id AS habit
           FROM ( SELECT t.habit_id
                       , DATE(t.created_at) AS `date`
                    FROM habit_progress_logs t
                   CROSS
                    JOIN (SELECT @prev := NULL, @prevDate := NULL, @streak := 1) i
                   GROUP BY t.habit_id, DATE(t.created_at)
                   ORDER BY t.habit_id, DATE(t.created_at)
                ) o
       ) s
  WHERE s.habit = 4
 GROUP BY s.habit

带有模式和数据的 SQLFiddle

mysql
  • 1 1 个回答
  • 53 Views

1 个回答

  • Voted
  1. Best Answer
    user1191247
    2023-08-19T01:05:26+08:002023-08-19T01:05:26+08:00

    您忘记了为每一行进行设置@prevDate,并且您返回的是最大条纹而不是最近的条纹。

    如果您使用 MySQL >= 8.0,您可以使用窗口函数,而不是表达式中已弃用的用户变量设置:

    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添加用于说明):

    习惯ID dt rnk 组
    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执行 GROUP BY 并添加ROW_NUMBER():

    习惯ID 组 长度 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

    • 1

相关问题

  • Wordpress - 媒体库 - SQL 语法

  • docker-compose:无法将应用程序服务连接到 mysql 数据库,收到“错误:用户‘root’@‘localhost’访问被拒绝(使用密码:YES)

  • MySQL 运行自动脚本

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    使用 <font color="#xxx"> 突出显示 html 中的代码

    • 2 个回答
  • Marko Smith

    为什么在传递 {} 时重载解析更喜欢 std::nullptr_t 而不是类?

    • 1 个回答
  • Marko Smith

    您可以使用花括号初始化列表作为(默认)模板参数吗?

    • 2 个回答
  • Marko Smith

    为什么列表推导式在内部创建一个函数?

    • 1 个回答
  • Marko Smith

    我正在尝试仅使用海龟随机和数学模块来制作吃豆人游戏

    • 1 个回答
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 个回答
  • Marko Smith

    为什么 'char -> int' 是提升,而 'char -> Short' 是转换(但不是提升)?

    • 4 个回答
  • Marko Smith

    为什么库中不调用全局变量的构造函数?

    • 1 个回答
  • Marko Smith

    std::common_reference_with 在元组上的行为不一致。哪个是对的?

    • 1 个回答
  • Marko Smith

    C++17 中 std::byte 只能按位运算?

    • 1 个回答
  • Martin Hope
    fbrereto 为什么在传递 {} 时重载解析更喜欢 std::nullptr_t 而不是类? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 您可以使用花括号初始化列表作为(默认)模板参数吗? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi 为什么列表推导式在内部创建一个函数? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A fmt 格式 %H:%M:%S 不带小数 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python C++20 的 std::views::filter 未正确过滤视图 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute 为什么 'char -> int' 是提升,而 'char -> Short' 是转换(但不是提升)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa 为什么库中不调用全局变量的构造函数? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis std::common_reference_with 在元组上的行为不一致。哪个是对的? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev 为什么编译器在这里错过矢量化? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan C++17 中 std::byte 只能按位运算? 2023-08-17 17:13:58 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve