需求:有一個用戶登陸日志表,記錄用戶每次登陸時間,然後想查找用戶按天連續登陸的情況,找出每次連續登陸的最早時間和最後時間以及連續登陸天數。
--===========================================
由於長久未寫此類SQL,有點手生,本著走一步算一步的精神,慢慢來。
首先查看日志表
SELECT [Uid] ,[loginDate] FROM [dbo].[Member_LoginLog] WHERE [UID]=268
由於按天計算連續登陸,表中時間精確到毫秒,很難肉眼看出數據是否連續,於是考慮轉換數據
而又由於我們只關心最早登陸時間和最後登陸時間,因此我們可以先按照天來統計用戶最早登陸時間和最後登陸時間,並將時間轉換成對應天數
--============================================== --統計出用戶每天最早登陸時間和最後登陸時間 SELECT T1.[UID] ,DATEDIFF(DAY,'2014-01-01',LoginDate) AS DiffDays ,MAX(LoginDate) AS MaxLoginDate ,MIN(LoginDate) AS MinLoginDate INTO [dbo].[Member_LoginLog_Status1] FROM [dbo].[Member_LoginLog] T1 GROUP BY T1.[UID],DATEDIFF(DAY,'2014-01-01',LoginDate) --====================================== --查看效果 SELECT [UID] ,[DiffDays] ,[MaxLoginDate] ,[MinLoginDate] FROM [dbo].[Member_LoginLog_Status1] WHERE UID=268
從上圖很容易看出第二天沒連續登陸,是不是很容易看啊
接下來就是查找聯系的天數了,如果我們按照UID分組,然後對DiffDays來排序求出排名來,依據DiffDays的增長量和RID量便可以判斷出天數是否連續
SELECT ROW_NUMBER()OVER(PARTITION BY UID ORDER BY [DiffDays] ASC) AS RID, T1.* FROM [dbo].[Member_LoginLog_Status1] T1 WHERE [UID]=268
這樣我們便可以使用表的自連接來查找連續的登錄,由於需要按照用戶和天數來算出排名,因此我們可以先建立索引
CREATE CLUSTERED INDEX CIX_UID_Days ON [dbo].[Member_LoginLog_Status1] ( [UID],[DiffDays] )
然後再求連續區間:
--========================================== --查找連續的登錄 ;WITH Tem AS( SELECT ROW_NUMBER()OVER(PARTITION BY UID ORDER BY [DiffDays] ASC) AS RID, T1.* FROM [dbo].[Member_LoginLog_Status1] T1 ) ,Tem1 AS( SELECT ROW_NUMBER()OVER( PARTITION BY T1.[UID],T1.[DiffDays] ORDER BY T2.[diffdays]-T1.[diffdays] DESC) AS RID, T1.[UID], T1.MinLoginDate, T2.MaxLoginDate, T1.[diffdays] AS MinDiffDays, T2.[diffdays] AS MAXDiffDays FROM Tem AS T1 INNER JOIN Tem AS T2 ON T1.UID=T2.UID AND T1.[diffdays]<=T2.[diffdays] AND T2.[diffdays]-T1.[diffdays]= T2.RID-T1.RID ) SELECT [UID], MinLoginDate, MaxLoginDate, MinDiffDays, MAXDiffDays INTO [dbo].[Member_LoginLog_Status2] FROM Tem1 AS T1 WHERE T1.RID=1 --========================================= --檢查結果 SELECT [UID] ,[MinLoginDate] ,[MaxLoginDate] ,[MinDiffDays] ,[MAXDiffDays] FROM [dbo].[Member_LoginLog_Status2] WHERE [UID]=268