当前位置: 首页 > news >正文

SQL167 连续签到领金币

SQL167 连续签到领金币

题目描述

用户行为日志表 tb_user_log

iduidartical_idin_timeout_timesign_in
110102021-07-07 10:00:002021-07-07 10:00:091
210102021-07-08 10:00:002021-07-08 10:00:091
310102021-07-09 10:00:002021-07-09 10:00:421
41010

2021-07-10 10:00:00

2021-07-10 10:00:091
510102021-07-11 23:59:552021-07-11 23:59:591
610102021-07-12 10:00:282021-07-12 10:00:501
710102021-07-13 10:00:28

2021-07-13 10:00:50

1
810202021-10-01 10:00:282021-10-01 10:00:501
910202021-10-02 10:00:012021-10-02 10:01:501
1010202021-10-03 10:00:552021-10-03 11:00:591
1110202021-10-04 10:00:452021-10-04 11:00:550
1210202021-10-05 10:00:532021-10-05 11:00:591
1310202021-10-06 10:00:452021-10-06 11:00:551

(uid-用户ID, artical_id-文章ID, in_time-进入时间, out_time-离开时间, sign_in-是否签到)

场景逻辑说明

  • artical_id-文章ID代表用户浏览的文章的ID,特殊情况artical_id-文章ID0表示用户在非文章内容页(比如App内的列表页、活动页等)。注意:只有artical_id为0时sign_in值才有效。
  • 2021年7月7日0点开始,用户每天签到可以领1金币,并可以开始累积签到天数,连续签到的第3、7天分别可额外领2、6金币
  • 每连续签到7天后重新累积签到天数(即重置签到天数:连续第8天签到时记为新的一轮签到的第一天,领1金币)

问题

计算每个用户2021年7月以来每月获得的金币数(该活动到10月底结束,11月1日开始的签到不再获得金币)。结果按月份、ID升序排序。

:如果签到记录的in_time-进入时间和out_time-离开时间跨天了,也只记作in_time对应的日期签到了

输出示例

示例数据的输出结果如下:

uidmonthcoin
10120210715
1022021107

解释:

101在活动期内连续签到了7天,因此获得1*7+2+6=15金币;

102在10.01~10.03连续签到3天获得5金币

10.04断签了,10.05~10.06连续签到2天获得2金币,共得到7金币。


思路

参考大佬:题解 | #连续签到领金币# 解题思路总结_牛客博客

问题理解

我们需要计算每个用户在2021年7月至10月期间,每月通过签到获得的金币总数。签到规则如下:

  1. 每天签到可获得1金币
  2. 连续签到第3天额外获得2金币
  3. 连续签到第7天额外获得6金币
  4. 每连续签到7天后重新开始计算(第8天视为新一轮的第1天)

解题思路

步骤1:提取有效签到记录

首先需要从用户行为日志中筛选出符合条件的签到记录:

  • 时间范围:2021-07-07至2021-10-31
  • 文章ID为0(表示在非文章页面)
  • 签到位为1(表示成功签到)
SELECT DISTINCTuid,DATE(in_time) AS sign_date
FROM tb_user_log
WHERE in_time BETWEEN '2021-07-07 00:00' AND '2021-10-31 23:59'AND artical_id = 0AND sign_in = 1

步骤2:识别连续签到分组

为了计算连续签到天数,我们使用一个技巧:用签到日期减去行号,相同结果的日期属于同一连续签到组

SELECT uid,sign_date,DATE_SUB(sign_date, INTERVAL ROW_NUMBER() OVER (PARTITION BY uid ORDER BY sign_date) DAY) AS group_date
FROM sign_dates

例如:

  • 用户连续签到3天:2021-07-07、2021-07-08、2021-07-09
  • 计算 group_date:
    • 2021-07-07 - 1天 = 2021-07-06
    • 2021-07-08 - 2天 = 2021-07-06
    • 2021-07-09 - 3天 = 2021-07-06
      这三个日期的 group_date 相同,表示它们是连续的

步骤3:计算连续签到天数

在每组内,按日期排序并编号,得到连续签到天数。

SELECT uid,sign_date,ROW_NUMBER() OVER (PARTITION BY uid, group_date ORDER BY sign_date) AS continuous_day
FROM sign_groups

步骤4:计算每日金币

根据连续签到天数计算每日获得的金币:

  • 第3天:1基础金币 + 2额外 = 3金币
  • 第7天:1基础金币 + 6额外 = 7金币
  • 其他天数:1金币
SELECT uid,sign_date,CASE WHEN continuous_day % 7 = 3 THEN 3WHEN continuous_day % 7 = 0 THEN 7ELSE 1END AS coin
FROM continuous_days

步骤5:按月汇总金币

最后,按用户ID和月份分组,汇总金币总数。

SELECT uid,DATE_FORMAT(sign_date, '%Y%m') AS month,SUM(coin) AS coin
FROM daily_coins
GROUP BY uid, DATE_FORMAT(sign_date, '%Y%m')
ORDER BY month, uid

关键点

  1. 连续签到识别​:通过日期减去行号的方法识别连续签到组
  2. 金币计算规则​:正确处理第3天和第7天的额外金币
  3. 7天周期重置​:使用模运算(continuous_day % 7)实现7天后重置

代码

WITH 
-- 获取有效的签到日期
sign_dates AS (SELECT DISTINCTuid,DATE(in_time) AS sign_dateFROM tb_user_logWHERE in_time BETWEEN '2021-07-07 00:00' AND '2021-10-31 23:59'AND artical_id = 0AND sign_in = 1
),-- 计算连续签到分组
sign_groups AS (SELECT uid,sign_date,-- 计算连续签到分组标识DATE_SUB(sign_date, INTERVAL ROW_NUMBER() OVER (PARTITION BY uid ORDER BY sign_date) DAY) AS group_dateFROM sign_dates
),-- 计算每组内的连续签到天数
continuous_days AS (SELECT uid,sign_date,-- 计算每组内的连续签到天数ROW_NUMBER() OVER (PARTITION BY uid, group_date ORDER BY sign_date) AS continuous_dayFROM sign_groups
),-- 计算每日金币
daily_coins AS (SELECT uid,sign_date,CASE WHEN continuous_day % 7 = 3 THEN 3  -- 第3天额外2金币WHEN continuous_day % 7 = 0 THEN 7  -- 第7天额外6金币ELSE 1                              -- 其他天1金币END AS coinFROM continuous_days
)-- 最终按月汇总
SELECT uid,DATE_FORMAT(sign_date, '%Y%m') AS month,SUM(coin) AS coin
FROM daily_coins
GROUP BY uid, DATE_FORMAT(sign_date, '%Y%m')
ORDER BY month, uid;
http://www.dtcms.com/a/306025.html

相关文章:

  • MySQL 9 Group Replication维护
  • 达梦数据库(DM Database)角色管理详解|了解DM预定义的各种角色,掌握角色创建、角色的分配和回收
  • C++:STL中list的使用和模拟实现
  • Keepalived 实战
  • 《C++二叉搜索树原理剖析:从原理到高效实现教学》
  • 如何利用 Redis 的原子操作(INCR, DECR)实现分布式计数器?
  • Java 控制台用户登录系统(支持角色权限与自定义异常处理)
  • 生成模型实战 | GLOW详解与实现
  • 从理论到实践:全面解析机器学习与 scikit-learn 工具
  • 汽车、航空航天、适用工业虚拟装配解决方案
  • 关于“PromptPilot” 之4 -目标系统软件架构: AI操作系统设计
  • 第六章:进入Redis的List核心
  • 【8月优质EI会议合集|高录用|EI检索稳定】计算机、光学、通信技术、电子、建模、数学、通信工程...
  • 人工智能与家庭:智能家居的便捷与隐患
  • 移动端WebView调试实战 全面排查渲染性能与布局跳动问题
  • ISO 26262 汽车功能安全(腾讯混元)
  • MongoDB系列教程-第二章:MongoDB数据库概念和特点、数据库操作、集合操作、文档操作、规范及常见问题解决、实际应用示例
  • JXD进步25.7.30
  • Thales靶机
  • 《Vuejs设计与实现》第 12 章(组件实现原理 下)
  • 非凸科技受邀出席第九届AIFOF投资创新发展论坛
  • 前端安全防护:XSS、CSRF与SQL注入漏洞深度解析与防御
  • 亚马逊云科技:赋能企业数字化转型,解决实际发展难题
  • 【Axure高保真原型】轮播条形图
  • 让科技之光,温暖银龄岁月——智绅科技“智慧养老进社区”星城国际站温情纪实
  • 【HarmonyOS】鸿蒙应用HTTPDNS 服务集成详解
  • 【Lua】元表常用属性
  • 【MySQL】MySQL索引—B树/B+树
  • 【选型】HK32L088 与 STM32F0/L0 系列 MCU 参数对比与选型建议(ST 原厂 vs 国产芯片)
  • 【LINUX网络】使用TCP简易通信