最大连续天数的问题也是非常常见的一个题型,比较常见的形式就是连续签到n次以上的人数,统计最大连续登录天数等等。
最大连续天数的有一个较为通用的解法,这个通用解法放在后面具体描述。
解题思路
首先思考一个简单的问题,怎么统计连续两天登录人数:连续两天登录就是一个人在登录后第二天继续登录了,只要找到登录日期的第二天有登录记录就行了。显然通过自连接,很容易就能够做到。
然后是连续三天登录人数,显然通过两次自连接,同样能够得到连续三天登录的人数。但是当连续n天登录人群的n足够大的时候,比如7天连续登录,30天连续登录,再用自连接来做就很难完成了。
从这个角度发散一下,连续n天登录就是为了找到连续的一段日期,如果对日期进行排序(假设日期没有重复),每一段连续的日期,减去它的排名,得到的日期是相同的。
| 日期 | 排名 | 差值 |
|---|---|---|
| 1-1 | 1 | 1-0 |
| 1-2 | 2 | 1-0 |
| 1-3 | 3 | 1-0 |
| 1-6 | 4 | 1-2 |
| 1-10 | 5 | 1-5 |
| 1-11 | 6 | 1-5 |
| 1-12 | 7 | 1-5 |
在得到差值之后,很显然,统计相同值出现的次数就是连续登录的天数,同样,相同值出现的最大次数就是最大连续登录天数。
解题步骤
为了实现上述想法,需要一步一步构建需要的数据,第一步:对登录日期进行排序,这里就要用到窗口函数了,如果没有重复值直接用row_number()就行,如果有重复值就要用dense_rank()了。
第二步:计算日期与排名的差值,这里需要使用时间函数,一般来说date_sub()就可以了,如果日期格式较为复杂,在上一步可以对其用date_format()进行修改格式,也可以用其他形式的时间差函数。
第三步,对差值进行统计。这里直接用group by进行聚类就行了。
示例
这里拿牛客网上的一道题来做示例(SQL29 某宝店铺连续2天及以上购物的用户及其对应的天数)
11月结束后,小牛同学需要对其在某宝的网店就11月份用户交易情况和产品情况进行分析以更好的经营小店。11月份销售数据表sales_tb如下(其中,sales_date表示销售日期,user_id指用户编号,item_id指货号,sales_num表示销售数量,sales_price表示结算金额):
请你统计连续2天及以上在该店铺购物的用户及其对应的次数(若有多个用户,按user_id升序排序),以上例子的输出结果如下:
#第三步 进行统计
select b.user_id,count(diff_date) as days_count
from (
#第二步 计算差值
select a.user_id,a.sales_date,date_sub(a.sales_date,INTERVAL rn day ) diff_date
from (
#第一步 进行排序
select user_id,
sales_date,
row_number() over (partition by user_id order by sales_date) rn
from sales_tb) a
)b
group by b.user_id,diff_date
having days_count>=2
order by user_id