SQL面試題1:連續登陸問題

引言

場景介紹:

許多互聯網平臺為了提高用戶的參與度和忠誠度,會推出各種連續登錄獎勵機制。例如,游戲平臺會給連續登錄的玩家發放游戲道具、金幣等獎勵;學習類 APP 會為連續登錄學習的用戶提供積分,積分可兌換課程或其他福利。通過這些激勵措施,平臺希望用戶能夠養成持續使用產品的習慣,從而提升產品的活躍度和留存率。同時,對于平臺運營者來說,分析用戶的連續登錄數據可以了解用戶的使用習慣和忠誠度,進而優化產品功能和運營策略。

題目描述:

假設我們有一個記錄用戶登錄信息的表,表名為 login_table,其中包含兩個字段:uid(用戶 ID)和 dt(登錄日期)。現在需要完成以下三個任務:

  1. 查詢連續登錄超過三天的用戶:找出在一段時間內,連續登錄天數大于三天的用戶列表。這有助于平臺識別出那些高度活躍且對產品有較高忠誠度的用戶,以便進一步進行精細化運營和獎勵。
  2. 查詢每個用戶連續登錄的最大天數:對于每個用戶,統計其在所有登錄記錄中連續登錄的最長時間段,這能幫助我們了解不同用戶的活躍程度差異,為個性化運營提供數據基礎。
  3. 查詢一個用戶連續登錄的最大天數(可隔一天):在計算用戶連續登錄天數時,允許中間間隔一天,只要整體登錄天數最多,就是我們要找的結果。比如用戶在 1、3、5、6 日登錄,那么其連續登錄的最大天數為 6 天。這種統計方式可以更靈活地評估用戶的活躍程度,考慮到了用戶可能因為某些特殊情況中斷一天登錄,但整體仍保持較高的使用頻率。

數據準備與代碼實現

數據準備

1	2025-01-01
1	2025-01-02
1	2025-01-03
2	2025-01-07
2	2025-01-08
3	2025-01-09
3	2025-01-10
3	2025-01-12
3	2025-01-13

1. 查詢連續登錄超過三天的用戶

思路:

  1. 用戶登錄記錄編號:利用row_number()函數按uid分區并依dt升序排序生成序號rn,實現對各用戶登錄時間進行排序編號
  2. 計算連續登錄首日:利用date_add函數將dt減去rn,計算每行對應的連續登錄起始日期first_day
  3. 選出連續登錄超過三天大用戶:利用group byuidfirst_day分組,結合having篩選出分組行數大于等于3的記錄,實現找出連續登錄超三天的用戶uid
with data as (select 1 as uid,'2025-01-01' as dt union allselect 1 as uid,'2025-01-02' as dt union allselect 1 as uid,'2025-01-03' as dt union allselect 2 as uid,'2025-01-07' as dt union allselect 2 as uid,'2025-01-08' as dt union allselect 3 as uid,'2025-01-09' as dt union allselect 3 as uid,'2025-01-10' as dt union allselect 3 as uid,'2025-01-12' as dt union allselect 3 as uid,'2025-01-13' as dt
),
data2 as (select uid,dt,row_number() over (partition by uid order by dt) rn from data
),
data3 as (select uid,dt,rn,date_add(dt,-rn) as first_day from data2
)
select uid from data3 group by uid,first_day having count(1) >= 3;

2. 查詢每個用戶連續登錄的最大天數

思路:

  1. 用戶登錄記錄編號:利用窗口函數row_number(),按uid分區并依dt升序排序生成序號rn,實現對各用戶登錄時間進行排序編號。
  2. 計算連續登錄首日:利用date_add函數將dt減去rn,計算每行對應的連續登錄起始日期first_day
  3. 統計分組登錄天數:利用group byuidfirst_day分組,通過count(*)統計同一組合的天數login_day,以此統計出每個用戶每段連續登錄的天數。
  4. 獲取用戶最大連續登錄天數:再次使用group byuid進行分組,通過max(login_day)從每個用戶的多段連續登錄天數中選出最大值,最終得到每個用戶連續登錄的最大天數。
with data as (select 1 as uid,'2025-01-01' as dt union allselect 1 as uid,'2025-01-02' as dt union allselect 1 as uid,'2025-01-03' as dt union allselect 2 as uid,'2025-01-07' as dt union allselect 2 as uid,'2025-01-08' as dt union allselect 3 as uid,'2025-01-09' as dt union allselect 3 as uid,'2025-01-10' as dt union allselect 3 as uid,'2025-01-12' as dt union allselect 3 as uid,'2025-01-13' as dt
),
data2 as (select uid,dt,row_number() over (partition by uid order by dt) rn from data
),
data3 as (select uid,dt,rn,date_add(dt,-rn) as first_day from data2
),
data4 as (select uid,first_day,count(*) as login_day from data3 group by uid,first_day)
select uid,max(login_day) from data4 group by uid;

3. 查詢一個用戶連續登錄的最大天數,可以隔一天。解釋:1、3、5、6登錄則最大登錄天數為6天。

思路:

  1. 查找上次登錄時間:利用lag函數按uid分區并依dt升序排序,實現獲取每行記錄的上一次登錄時間prev_dt
  2. 打標判斷連續登錄:利用datediff函數計算dtprev_dt的時間差,根據差值情況打標flag,實現區分是否連續登錄,如果差值小于2天或者null(表示第一天)標記為0,都則標記為1。
  3. 計算連續登錄標識和:利用sum函數按uid分組并依dt升序對flag求和,生成sum_flag,實現標識連續登錄段。
  4. 計算每組時間差值:利用datediff函數對uidsum_flag聚類分組后計算max(dt)min(dt)的差值,實現獲取每個分組的時間跨度。
  5. 獲取最大連續登錄天數:利用分組和max函數選出每個用戶的最大時間差值max(diff)+1,實現得到每個用戶連續登錄的最大天數max_login

核心點:將相差值小于等于2的分到同一組里,然后采用分段思想計算每個分組分段的天數即為連續登錄的天數。

with data as (select 1 as uid,'2025-01-01' as dt union allselect 1 as uid,'2025-01-02' as dt union allselect 1 as uid,'2025-01-04' as dt union allselect 2 as uid,'2025-01-07' as dt union allselect 2 as uid,'2025-01-08' as dt union allselect 2 as uid,'2025-01-11' as dt union allselect 2 as uid,'2025-01-13' as dt union allselect 2 as uid,'2025-01-15' as dt union allselect 3 as uid,'2025-01-09' as dt union allselect 3 as uid,'2025-01-10' as dt union allselect 3 as uid,'2025-01-12' as dt union allselect 3 as uid,'2025-01-15' as dt
),
data2 as (select uid,dt,lag(dt, 1) over (partition by uid order by dt) prev_dt from data
),
data3 as (select uid,dt,prev_dt,if(datediff(dt, prev_dt) <= 2 or datediff(dt, prev_dt) is null, 0 ,1) flag from data2
),
data4 as (select uid,dt,prev_dt,flag,sum(flag) over(partition by uid order by dt) as sum_flag from data3
),
data5 as (select uid,datediff(max(dt),min(dt)) diff from data4 group by uid,sum_flag
)
select uid,max(diff)+1 as max_login from data5 group by uid;

知識點總結

1.窗口函數:lag、row_number

https://blog.csdn.net/Ahuuua/article/details/127136611

基本語法:函數名(參數) OVER (PARTITION BY 子句 ORDER BY 子句 ROWS/RANGE子句)

  • 函數名:如sum、max、min、count、avg等聚合函數以及lead、lag行比較函數等;
  • over: 關鍵字,表示前面的函數是分析函數,不是普通的集合函數;
  • 分組子句:over關鍵字后面掛號內的內容
lag()比較窗口函數

lag/lead(arg1,arg2,arg3):其中arg1為列名;arg2為偏移值,不能為負,默認為1;arg3超出記錄窗口時的默認值,當不指定默認值時,則為null。lag:向前取n行; lead:向后取n行
在這里插入圖片描述

row_number()排序窗口函數

排序窗口函數的主要作用是為查詢結果中的每一行數據生成一個唯一的行號。這個行號是基于特定的排序規則生成的,并且可以根據不同的分組條件進行獨立編號。

rankrow_numberdense_rank
100111
100121
90332

2. 日期計算函數

日期的三種形式:

  • DATE:YYYY-MM-DD,CURRENT_DATE()
  • DATETIME:YYYY-MM-DD HH:MM:SS、CURRENT_TIMESTAMP()
  • TIMESTAMP:時間戳,1973-12-30 15:30:00為19731230153000,UNIX_TIMESTAMP()
    常見計算函數:
  • DATEDIFF(end,start):計算end-start,單位天數
  • TIMESTAMPDIFF(unit,start,end):計算end-start,單位unit
    • unit:second、minute、hour、day、week、month、quarter(季度)、year
  • DATE_ADD(date, num):計算date+num后的時間,num參數表示要增加的時間間隔數量,正數表示增加時間,負數表示減少時間。
select CURRENT_DATE(),CURRENT_TIMESTAMP(),UNIX_TIMESTAMP();

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/66039.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/66039.shtml
英文地址,請注明出處:http://en.pswp.cn/web/66039.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

爬山算法與模擬退火算法的全方面比較

一、基本概念與原理 1. 爬山算法 爬山算法是一種基于啟發式的局部搜索算法,通過不斷地向當前解的鄰域中搜索更優解來逼近全局最優解。它的核心思想是,從當前解出發,在鄰域內找到一個使目標函數值更大(或更小)的解作為新的當前解,直到找不到更優的解為止。 2.模擬退火算…

PostgreSQL 超級管理員詳解

1. 什么是 PostgreSQL 超級管理員 PostgreSQL 超級管理員&#xff08;superuser&#xff09;是擁有數據庫系統最高權限的用戶。他們可以執行任何數據庫操作&#xff0c;包括但不限于創建和刪除數據庫、用戶、表空間、模式等。超級管理員權限是 PostgreSQL 中權限的最高級別。 …

安裝本地測試安裝apache-doris

一、安裝前規劃 我的服務器是三臺麒麟服務器,2臺跑不起來,這是我本地的,內存分配的也不多。 fe192.168.1.13 主數據庫端口9030訪問 8Gbe192.168.1.13內存4G 硬盤50be192.168.1.14內存4G 硬盤50be192.168.1.12內存4G 硬盤5013同時安裝的fe和be 。 原理:192.168.1.13 服…

GPT(General Purpose Timer)定時器

基本概念&#xff1a; 在嵌入式系統中&#xff0c;General Purpose Timer&#xff08;GPT&#xff09;是一種非常重要的硬件組件&#xff0c;用于提供定時功能。 定義&#xff1a;通用定時器是一種能夠提供精確時間測量和控制功能的電子設備或電路模塊。它可以產生周期性的時…

集中式架構vs分布式架構

一、集中式架構 如何準確理解集中式架構 1. 集中式架構的定義 集中式架構是一種將系統的所有計算、存儲、數據處理和控制邏輯集中在一個或少數幾個節點上運行的架構模式。這些中央節點&#xff08;服務器或主機&#xff09;作為系統的核心&#xff0c;負責處理所有用戶請求和…

數據挖掘實訓:天氣數據分析與機器學習模型構建

隨著氣候變化對各行各業的影響日益加劇&#xff0c;精準的天氣預測已經變得尤為重要。降雨預測在日常生活中尤其關鍵&#xff0c;例如農業、交通和災害預警等領域。本文將通過機器學習方法&#xff0c;利用歷史天氣數據預測明天是否會下雨&#xff0c;具體內容包括數據預處理、…

kalilinux - 目錄掃描之dirsearch

情景導入 先簡單介紹一下dirsearch有啥用。 假如你現在訪問一個網站&#xff0c;例如https://www.example.com/ 它是一個電商平臺或者其他功能性質的平臺。 站在開發者的角度上思考&#xff0c;我們只指導https://www.example.com/ 但不知道它下面有什么文件&#xff0c;文…

關于 ThinkPHP 與 PostgreSQL 結合使用的一些要點

ThinkPHP 是一款流行的 PHP 開發框架&#xff0c;而 PostgreSQL 是功能強大的開源關系型數據庫。它們可以結合使用來開發各類應用&#xff0c;以下是關于 ThinkPHP 與 PostgreSQL 結合使用的一些要點&#xff1a; 配置數據庫連接 編輯配置文件&#xff1a;在 ThinkPHP 項目中&…

進程同步之信號量機制

信號量機制 信號量機制是一種用于進程同步和互斥的基本工具&#xff0c;特別是在并發編程中&#xff0c;廣泛用于控制對共享資源的訪問&#xff0c;避免數據競爭和死鎖等問題。信號量機制由荷蘭計算機科學家Edsger Dijkstra在1965年提出&#xff0c;并在操作系統的進程同步中發…

SOME/IP協議詳解 基礎解讀 涵蓋SOME/IP協議解析 SOME/IP通訊機制 協議特點 錯誤處理機制

車載以太網協議棧總共可劃分為五層&#xff0c;分別為物理層&#xff0c;數據鏈路層&#xff0c;網絡層&#xff0c;傳輸層&#xff0c;應用層&#xff0c;其中今天所要介紹的內容SOME/IP就是一種應用層協議。 SOME/IP協議內容按照AUTOSAR中的描述&#xff0c;我們可以更進一步…

springboot vue uniapp 仿小紅書 1:1 還原 (含源碼演示)

線上預覽: 移動端 http://8.146.211.120:8081/ 管理端 http://8.146.211.120:8088/ 小紅書憑借優秀的產品體驗 和超高人氣 目前成為筆記類產品佼佼者 此項目將詳細介紹如何使用Vue.js和Spring Boot 集合uniapp 開發一個仿小紅書應用&#xff0c;憑借uniapp 可以在h5 小程序 app…

基于celery的任務管理,本文主要是處理自己的算法,暴露API,管理任務并發,多線程

基于celery的任務管理&#xff0c;本文主要是處理自己的算法&#xff0c;暴露API&#xff0c;管理任務并發&#xff0c;多線程 基本需求描述潛在問題主函數配置文件 基本需求描述 暴露API&#xff0c;供其他人調用算法。方便查看任務狀態。因為服務器資源有限&#xff0c;控制…

Java(7)常用的工具類

1.Collections集合工具類 內置了大量對集合操作的靜態方法&#xff0c;可以通過類名直接調用方法。 方法的種類&#xff1a;最大值max、最小值min、sort排序...詳見API幫助文檔 import java.util.ArrayList; import java.util.Collections; import java.util.List;public cl…

【Varnish】:解決 Varnish 7.6 CDN 靜態資源緩存失效問題

項目場景&#xff1a; 在一個使用Varnish作為反向代理的Web應用中&#xff0c;我們依賴CDN&#xff08;內容分發網絡&#xff09;來緩存靜態資源&#xff08;如圖片、CSS、JavaScript文件等&#xff09;&#xff0c;以提高全球用戶的訪問速度并減輕源站服務器的負載。然而&…

理解機器學習中的參數和超參數

在機器學習中&#xff0c;參數和超參數是兩個重要但不同的概念&#xff0c;它們共同影響模型的性能和表現。以下是它們的定義和區別&#xff0c;以及如何通俗地理解它們&#xff1a; 1. 參數 定義 參數是模型在訓練過程中自動學習到的變量&#xff0c;它們直接決定了模型如何…

Win11右鍵菜單實現

主要參考Win11 Context Menu Demo 此工程是vs2022編譯&#xff0c;vs2019先修改下 base.h 方可編譯過 編譯好dll以后 拷貝至SparsePackage目錄下 生成稀疏包msix 就拿他工程里面的改&#xff0c;編輯AppxManifest.xml&#xff0c;配置都要對&#xff0c;一個不對可能都失敗&a…

R.swift庫的詳細用法

R.swift 是一個 Swift 工具庫,它提供了一個自動生成的類 R,使得你可以通過類型安全的方式訪問項目中的資源,例如圖片、字體、顏色、XIB 文件等。通過 R.swift,你可以避免字符串類型的錯誤,提升代碼的可維護性。 以下是 R.swift 庫的詳細用法: 1. 安裝 R.swift 使用 Sw…

像JSONDecodeError: Extra data: line 2 column 1 (char 134)這樣的問題怎么解決

問題介紹 今天處理返回的 JSON 的時候&#xff0c;出現了下面這樣的問題&#xff1a; 處理這種問題的時候&#xff0c;首先你要看一下當前的字符串格式是啥樣的&#xff0c;比如我查看后發現是下面這樣的&#xff1a; 會發現這個字符串中間沒有逗號&#xff0c;也就是此時的J…

what?ngify 比 axios 更好用,更強大?

文章目錄 前言一、什么是ngify&#xff1f;二、npm安裝三、發起請求3.1 獲取 JSON 數據3.2 獲取其他類型的數據3.3 改變服務器狀態3.4 設置 URL 參數3.5 設置請求標頭3.6 與服務器響應事件交互3.7 接收原始進度事件3.8 處理請求失敗3.9 Http Observables 四、更換 HTTP 請求實現…

Linux Kernel 之十 詳解 PREEMPT_RT、Xenomai 的架構、源碼、構建及使用

概述 現在的 RTOS 基本可以分為 Linux 陣營和非 Linux 陣營這兩大陣營。非 Linux 陣營的各大 RTOS 都是獨立發展,使用上也相對獨立;而 Linux 陣營則有多種不同的實現方法來改造 Linux 以實現實時性要求。本文我們重點關注 Linux 陣營的實時內核實現方法! 本文我們重點關注 …