日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Sql如何统计连续打卡天数

發布時間:2023/12/19 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Sql如何统计连续打卡天数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

總第208篇/張俊紅

今天來解一道題面試中可能經常會被一些面試官拿來“刁難”的題,就是《如何統計連續打卡天數》,當然了這里面的打卡可以換成任意其他行為,比如連續登陸天數,連續學習天數,連續購買天數,這里的天數也是可以換成小時或者別的時間單位的。這個問題的邏輯還是有點復雜,如果要是之前沒遇到過這種問題,當場被問到的時候,肯定會一臉懵。

直接來看實戰,現在有一張表t,這張表存儲了每個員工每天的打卡情況,現在需要統計截止目前每個員工的連續打卡天數,表t如下表所示:

uidtdateis_flag
12020/2/11
12020/2/20
12020/2/31
12020/2/41
12020/2/50
12020/2/61
12020/2/71
12020/2/81
22020/2/11
22020/2/20
22020/2/30
22020/2/41
22020/2/51
22020/2/61
22020/2/71
22020/2/81

上表中uid是用戶id,tdate是日期,is_flag是記錄用戶當天是否打卡,1為打卡,0為未打卡。

我們希望得到的結果為:

uidflag_days
13
25

這個邏輯還是挺難想的,第一個想法就是通過前后數據偏移來實現,就是將is_flag向前移動一行或者向后移動一行,然后和原來的is_flag標簽做差,如果結果為0,說明前后兩天的值是相同的,要么都是0,要么都是1。但是還是不能夠得出我們想要的結果。

再換一種思路:如果是連續打卡,那么打卡日期與一個遞增的數字依次做差的結果值應該是相等的,不理解這句話沒關系,看具體結果你就明白了。

我們先獲取每個用戶在這一段時間內所有打卡的排名,是所有打卡的排名哦,利用的是窗口函數的row_number(),代碼如下:

select??uid,tdate,row_number()?over(partition?by?uid?order?by?tdate)?date_rank fromt where?is_flag=1

運行上面的代碼,可以得到如下結果:

uidtdatedate_rank
12020/2/11
12020/2/32
12020/2/43
12020/2/64
12020/2/75
12020/2/86
22020/2/11
22020/2/42
22020/2/53
22020/2/64
22020/2/75
22020/2/86

接著再獲取每個打卡日期(tdate)中的日與其打卡日期排名(date_rank)之間的差,比如uid=1的2020/2/3的打卡日期中的3號與其排名(date_rank)2做差等于1,實現代碼如下:

select?uid,tdate,date_rank,(date_format(tdate,"%e")?-?date_rank)?as?day_cha from?(select??uid,tdate,row_number()?over(partition?by?uid?order?by?tdate)?date_rankfromdemo.newtablewhere?is_flag=1)t1

運行上面的代碼,最后可以得到如下結果:

uidtdatedate_rankday_cha
12020/2/110
12020/2/321
12020/2/431
12020/2/642
12020/2/752
12020/2/862
22020/2/110
22020/2/422
22020/2/532
22020/2/642
22020/2/752
22020/2/862

看上面的結果表,有沒有看出點意思來,連續打卡日期的day_cha都是相等的,比如uid=1的2020/2/3和2020/2/4是連續的,他們的day_cha都是1。到這里,如果我們要獲取連續打卡天數是不是就很容易了。

不過這里面還有一個問題,就是連續打卡天數是截止目前最近的一個 連續打卡天數還是歷史堅持最長的打卡天數,這就是傳說中的口徑問題哈。雖然在我們這個例子里面,這兩種打卡天數的出來的結果是一樣的,但是有的時候會是不一樣的,比如下面這樣的例子:

uidtdateis_flag
12020/2/11
12020/2/20
12020/2/31
12020/2/41
12020/2/51
12020/2/60
12020/2/71
12020/2/81

上面這個例子中,最近連續打卡天數是2,歷史最長的連續打卡天數卻是3。

好了,我們繼續回到解題上,我們先獲取每個用戶歷史所有連續過得的打卡情況,實現代碼如下:

select?uid,day_cha,count(tdate)?flag_days from?(select?uid,tdate,date_rank,(date_format(tdate,"%e")?-?date_rank)?as?day_cha from?(select??uid,tdate,row_number()?over(partition?by?uid?order?by?tdate)?date_rankfromdemo.newtablewhere?is_flag=1)t1)t2 group?by?uid,day_cha

運行上面的代碼,得到如下結果:

uidday_chaflag_days
101
112
123
201
225

要獲取最近的連續打卡天數,我們只需要把上表中day_cha這一列最大的值對應的flag_days取出來就可以;要獲取歷史最久的連續打卡天數,我們只需要把上表中flag_days的最大值取出來就可以。直接再來個子查詢就好了。

類似的需求可能還有獲取過去連續打卡天數大于某個值得人,只需要篩選上表中的flag_days即可達到目的。只要能夠生成上面這樣每個人歷史所有連續打卡的情況表,那么大部分連續打卡相關的需求都可以通過上表來獲得。

很經典的一道題,或者是一種業務場景,大家各自多多練習。

你還可以看:

講講你不知道的窗口函數

總結

以上是生活随笔為你收集整理的Sql如何统计连续打卡天数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。