【面試題】
有一張“用戶登陸記錄表”,包含兩個字段:用戶id、日期。
【問題】查詢2021年每個月,每個用戶連續登陸的最多天數。
【解題步驟】
1. 連續問題的萬能模板
在《拼多多面試題:如何找出連續出現N次的內容?》裏講過遇到“連續問題”如何解決,並送出了一個萬能模板,模板使用的是窗口函數解決連續問題。
2. 窗口函數
窗口函數lead使用方法:
默認值是指:當向上N行或者向下N行值時,如果已經超出了錶行和列的範圍時,會將這個默認值作爲函數的返回值,若沒有指定默認值,則返回Null。
窗口函數lead可以獲取每個字段的後面的第n個值,並生成新的一列。
而這道題描述的“用戶連續登陸”中的“連續”可以理解爲用戶當前的登陸日期與本月下一次登陸日期相差一天。
我們可以先用窗口函數lead獲取“用戶當月下一個登陸日期”:
當“日期”是該用戶在當月最後一天登陸時,記錄爲“當月最後登陸日期”,如果不進行設置,將會返回Null,不利於理解。
從結果看,我們可以獲得以下信息:
1)當“日期”與“用戶當月下一個登陸日期”只相差一天,即用戶本次登陸爲連續登陸;
2)當“日期”與“用戶當月下一個登陸日期”相差大於一天,即用戶本次登陸爲連續登陸的最後一天(也有可能僅登陸一天);
3)當“用戶當月下一個登陸日期”等於“當月最後登陸日期”,即用戶本次登陸爲本月最後一天登陸。
這樣,可以判斷用戶連續登陸的情況。
接下來就解決用戶每次連續登陸天數的計算。
3. 子查詢
用戶每次連續登陸天數與用戶登陸順序存在某種必然的關係,此時我們可以先用子查詢將用戶在本月的閱讀順序查詢出來,使用窗口函數row_number:
可以看出,當連續終止時,即:
1)“日期”與“用戶當月下一個登陸日期”相差大於一天;
2)“用戶當月下一個登陸日期”等於“當月最後登陸日期”;
兩種情況。
將這兩種情況過濾出來之後,用戶連續登陸天數爲:當前登陸順序減去上一個登陸順序。
“上一個登陸順序”爲Null時,用0代替(使用coalesce函數),那麼“每個月登陸順序”減去“上一個登陸順序”就是本次連續登陸天數。
4. 彙總分析
最後獲取“每個月,每個用戶連續登陸的最多天數”,使用group by函數。
【本題考點】
1.考查對窗口函數的瞭解,要把《猴子 從零學會SQL》裏講過的窗口函數能解決的4類面試題要記住;
2.考查對子查詢的瞭解;
3.考查對連續問題的瞭解,可以套用萬能模板。