SQL164 2021年11月每天新用戶的次日留存率

SQL164 2021年11月每天新用戶的次日留存率

思路

  1. ?找出新用戶?:確定每個用戶首次活躍的日期(即新用戶)

    • 例如101用戶在11月1日首次出現
  2. ?處理跨天活躍?:考慮用戶可能跨天活躍的情況(in_time和out_time不在同一天)

    • 例如用戶可能在11月1日23:50進入,11月2日00:10離開,則算作兩天都活躍
  3. ?計算次日留存?:

    • 對每個新用戶,檢查他們首次活躍后的第二天是否仍然活躍
    • 使用LEAD窗口函數高效獲取用戶下一次活躍日期
  4. ?計算留存率?:

    • 每天的新用戶數作為分母
    • 第二天仍然活躍的新用戶數作為分子
    • 兩者相除得到留存率,保留2位小數

最終輸出2021年11月每天新用戶的次日留存率,按日期排序。

代碼

WITH 
-- 獲取每個用戶的最早活躍日期作為其首次出現日期
first_occurrence AS (SELECT uid,DATE(MIN(in_time)) AS first_dtFROM tb_user_logGROUP BY uid
),-- 獲取每個用戶每天活躍的記錄(處理跨天情況)
user_active_dates AS (SELECT DISTINCT uid,DATE(in_time) AS active_dateFROM tb_user_logUNIONSELECT DISTINCT uid,DATE(out_time) AS active_dateFROM tb_user_log
),-- 為每個用戶按日期排序,并使用LEAD獲取下一天的活躍狀態
user_activity_sequence AS (SELECT uid,active_date,LEAD(active_date) OVER (PARTITION BY uid ORDER BY active_date) AS next_active_dateFROM user_active_dates
),-- 計算每天的新用戶數及其次日留存情況
daily_stats AS (SELECT fo.first_dt AS dt,COUNT(DISTINCT fo.uid) AS new_users,COUNT(DISTINCT CASE WHEN DATEDIFF(uas.next_active_date, fo.first_dt) = 1 THEN fo.uid END) AS retained_usersFROM first_occurrence foLEFT JOIN user_activity_sequence uas ON fo.uid = uas.uid AND fo.first_dt = uas.active_dateWHERE fo.first_dt BETWEEN '2021-11-01' AND '2021-11-30'GROUP BY fo.first_dt
)-- 計算并格式化留存率
SELECT dt,ROUND(IF(new_users = 0, 0, retained_users / new_users), 2) AS uv_left_rate
FROM daily_stats
ORDER BY dt;

逐步展示如何計算2021年11月每天新用戶的次日留存率

原始數據表 tb_user_log

iduidartical_idin_timeout_timesign_in
110102021-11-01 10:00:002021-11-01 10:00:421
210290012021-11-01 10:00:002021-11-01 10:00:090
310390012021-11-01 10:00:012021-11-01 10:01:500
410190022021-11-02 10:00:092021-11-02 10:00:280
510390022021-11-02 10:00:512021-11-02 10:00:590
610490012021-11-02 10:00:282021-11-02 10:00:500
710190032021-11-03 11:00:552021-11-03 11:01:240
810490032021-11-03 11:00:452021-11-03 11:00:550
910590032021-11-03 11:00:532021-11-03 11:00:590
1010190022021-11-04 11:00:552021-11-04 11:00:590

步驟1:確定每個用戶的首次活躍日期

SELECT uid,DATE(MIN(in_time)) AS first_dt
FROM tb_user_log
GROUP BY uid;

結果:

uidfirst_dt
1012021-11-01
1022021-11-01
1032021-11-01
1042021-11-02
1052021-11-03

步驟2:處理跨天情況,獲取用戶活躍日期

SELECT DISTINCT uid,DATE(in_time) AS active_date
FROM tb_user_log
UNION
SELECT DISTINCT uid,DATE(out_time) AS active_date
FROM tb_user_log;

結果:

uidactive_date
1012021-11-01
1012021-11-02
1012021-11-03
1012021-11-04
1022021-11-01
1032021-11-01
1032021-11-02
1042021-11-02
1042021-11-03
1052021-11-03

步驟3:使用LEAD函數獲取用戶的下一次活躍日期

SELECT uid,active_date,LEAD(active_date) OVER (PARTITION BY uid ORDER BY active_date) AS next_active_date
FROM user_active_dates;

結果:

uidactive_datenext_active_date
1012021-11-012021-11-02
1012021-11-022021-11-03
1012021-11-032021-11-04
1012021-11-04NULL
1022021-11-01NULL
1032021-11-012021-11-02
1032021-11-02NULL
1042021-11-022021-11-03
1042021-11-03NULL
1052021-11-03NULL

步驟4:計算每天的新用戶次日留存情況

SELECT fo.first_dt AS dt,COUNT(DISTINCT fo.uid) AS new_users,COUNT(DISTINCT CASE WHEN DATEDIFF(uas.next_active_date, fo.first_dt) = 1 THEN fo.uid END) AS retained_users
FROM first_occurrence fo
LEFT JOIN user_activity_sequence uas ON fo.uid = uas.uid AND fo.first_dt = uas.active_date
WHERE fo.first_dt BETWEEN '2021-11-01' AND '2021-11-30'
GROUP BY fo.first_dt;

結果:

dtnew_usersretained_users
2021-11-0132
2021-11-0211
2021-11-0310

詳細解釋一下

這個CTE是計算每日新用戶及其次日留存情況的核心部分,詳細拆解邏輯:

  1. ?數據來源?:

    • first_occurrence:包含每個用戶的首次活躍日期
    • user_activity_sequence:包含用戶每次活躍日期及下一次活躍日期(使用LEAD計算)
  2. ?連接條件?:

    LEFT JOIN user_activity_sequence uas 
    ON fo.uid = uas.uid 
    AND fo.first_dt = uas.active_date
    • 按用戶ID連接
    • 只連接用戶首次活躍當天的記錄(因為我們要計算的是新用戶的次日留存)
  3. ?計算字段?:

    • new_users:每天首次出現的用戶數(COUNT DISTINCT)
    • retained_users:這些新用戶中第二天仍然活躍的數量
  4. ?留存判斷邏輯?:

    CASE WHEN DATEDIFF(uas.next_active_date, fo.first_dt) = 1 THEN fo.uid 
    END
    • 計算用戶首次活躍日期與下一次活躍日期的差值
    • 如果差值為1天,則表示用戶次日活躍
  5. ?為什么用LEFT JOIN?:

    • 確保即使新用戶第二天不活躍,也會被計入分母(新用戶數)
    • 不活躍的用戶在CASE WHEN中會返回NULL,不會被COUNT計算

示例數據推演

以2021-11-01為例:

  • 新用戶:101、102、103
  • 檢查他們的次日活躍情況:
    • 101:11-02活躍(符合)
    • 102:11-02不活躍
    • 103:11-02活躍(符合)
  • 結果:3個新用戶,2個次日活躍 → 留存率2/3=0.67

這種設計確保了:

  1. 準確識別新用戶
  2. 正確處理跨天活躍情況
  3. 精確計算次日留存率

最終結果:計算留存率

SELECT dt,ROUND(IF(new_users = 0, 0, retained_users / new_users), 2) AS uv_left_rate
FROM daily_stats
ORDER BY dt;

最終輸出:

dtuv_left_rate
2021-11-010.67
2021-11-021.00
2021-11-030.00

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

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

相關文章

基于單片機的數字電壓表設計

2 系統原理及基本框圖 如圖2.1所示,模擬電壓經過檔位切換到不同的分壓電路衰減后,經隔離干擾送到A/D轉換器進行A/D轉換,然后送到單片機中進行數據處理。處理后的數據送到LCD中顯示,同時通過串行通訊與上位機通信。圖2.1系統基本方…

[NLP]UPF基本語法及其在 native low power verification中的典型流程

UPF基本語法及其在 native low power verification中的典型流程 摘要:本文首先簡要介紹 UPF(Unified Power Format),然后解釋其在 native low power verification(原生低功耗驗證)中的典型流程。最后,我將使用50個具體例子來完整展示 UPF 的關鍵語法。這些例子基…

fish-speech 在50系列顯卡使用 --compile加速兼容

#環境說明 GPU: NVIDIA GeForce RTX 5080 Laptop GPU (sm_120) win11家庭版 24H2 #問題匯總 baize.exceptions.HTTPException: (500, "RuntimeError: ptxas failed with error code 4294967295: \\n\\n") 問題匯總 1 baize.exceptions.HTTPException: (500, "…

UI自動化測試實戰

Python接口自動化測試零基礎入門到精通(2025最新版)一、設計背景 隨著IT行業的發展,產品愈漸復雜,web端業務及流程更加繁瑣,目前UI測試僅是針對單一頁面,操作量大。為了滿足多頁面功能及流程的需求及節省工…

面試實戰,問題六,被問數據庫索引,怎么回答

Java開發面試:數據庫索引的原理及常見問題解答 在Java開發面試中,數據庫索引是核心知識點,涉及數據庫優化和性能調優。索引通過高效的數據結構加速數據檢索,降低磁盤IO成本,并支持排序操作。下面我將逐步解釋索引的原理…

ARM-I2C硬實現

硬件I2C-GD32F4系列的實現初始化操作在初始化函數里執行以下代碼uint32_t i2cx_scl_port_rcu RCU_GPIOB; uint32_t i2cx_scl_port GPIOB; uint32_t i2cx_scl_pin GPIO_PIN_6; uint32_t i2cx_scl_af GPIO_AF_4;uint32_t i2cx_sda_port_rcu RCU_GPIOB; uint32_t i2cx_sda_po…

WinUI3開發_過渡動畫

簡介 過渡動畫是當發生事件時控件UI狀態發生改變時以一種動畫形式來演變到另外一種狀態,而非瞬間改變,使用一種更加平滑的方式來進行切換,例如下圖是文字切換的交叉柵欄效果:還有頁面切換動畫:在或者是圖標動畫&#x…

Linux下提權root權限

現在AI工具這么豐富,稍微搜一下就有一個差不多的總結輸出。但是,可能還不夠詳細,或者給得太多~~~今天時間關系,今天只總結了在Linux如何提權到root,并沒有寫如何進行防護。后面有時間,我再總結一下。命令實…

焊接機器人節能先鋒

汽車制造業中,機器人技術的應用已成為推動工業自動化和生產效率提升的重要力量。機器人在焊接、組裝、涂裝等關鍵制造環節中扮演著不可或缺的角色。隨著工業生產規模的不斷擴大,能源消耗和成本控制成為了企業必須面對的重大挑戰。尤其是工業焊接用氣的大…

MinIO:云原生對象存儲的終極指南

MinIO 是什么? MinIO 是一款高性能、云原生的對象存儲服務,具有以下優勢: 輕量級部署:采用 Go 語言編寫,資源占用低,支持快速部署 兼容性強:完全兼容 Amazon S3 API,輕松對接現有應用 高可用架構:支持分布式部署,確保數據持久性和服務可用性 高性能表現:專為云環境…

Spring AOP `MethodInvocation` 工作原理

?? 一、通知到 MethodInterceptor 的轉換機制 Spring AOP 通過適配器模式將開發者定義的注解型通知(如 Before)統一轉換為 MethodInterceptor 接口實現,確保所有通知類型能接入同一調用鏈。以下是轉換細節: 1. 適配器實現原理 核…

PPO原論文閱讀

一、Introduction1.目前存在的問題:(deep)Q-learning:在一些簡單問題上表現不佳,可理解性差基礎的policy gradient算法:(如REINFORCE)魯棒性差,需要大量數據TRPO:復雜,在包含噪音&am…

零基礎也能創作專屬歌曲:文心一言+蘑兔AI協同教程

在AI技術飛速發展的今天,音樂創作已不再是專業音樂人的專屬領域。通過文心一言與蘑兔AI的協同使用,即使沒有音樂基礎,也能輕松完成從歌詞創作到作曲編曲的全流程。本文將詳細拆解操作步驟,助你快速上手,實現音樂創作夢…

圖論:搜索問題

提到圖論中的搜索問題,首先想到的也就是DFS和BFS了,而提到這兩種搜索,那么最典型的題目就是島嶼問題了,下面就練習幾道相關的題目,為之后的更深奧的圖論學習打下基礎! 孤島的總面積 題目鏈接:…

AI驅動攻防升級,API安全走到關鍵檔口

在數字化轉型與AI技術快速發展的雙重驅動下,API已成為企業業務與外部世界連接的神經中樞。然而,隨著API的深度應用,針對API的攻擊規模與復雜性也在持續升級。 API為何頻頻成為黑客重點盯防的突破口?企業常見的API防護手段是否還能…

網絡基礎DAY18-動態路由協議基礎

動態路由協議基礎知識回顧:1.什么是路由? 答:是三層設備轉發IP報文的路徑信息。 2.路由有哪些來源? 答:1.直連路由2.靜態路由3.動態路由 3.有直連路由的條件? 答:1.二層和三層物理接口狀態為UP …

axios統一封裝規范管理

新建/api/ 1.新建統一處理文件/api/axios.ts import axios from "axios"const http axios.create({baseURL: import.meta.env.VITE_API_BASE_URL, // 從環境變量讀取timeout: 10000, });// 請求攔截器(如添加 Token) http.interceptors.reque…

Java學習第七十四部分——Elasticsearch(ES)

目錄 一、前言提要 二、核心特性 三、應用場景 四、主要優勢 五、集成方式 六、基礎操作 七、高級特性 八、概念類比——與關系型數據庫 九、簡單示例——實現存儲與搜索 十、生態集成——基于Spring Data Elasticsearch 十一、性能優化建議 十二、總結歸納概述 一…

TDengine 轉化函數 TO_UNIXTIMESTAMP 用戶手冊

TDengine TO_UNIXTIMESTAMP 函數用戶使用手冊 函數概述 TO_UNIXTIMESTAMP 是 TDengine 中的標量函數,用于將符合 ISO8601/RFC3339 標準的日期時間字符串轉換為 Unix 時間戳。與 TO_TIMESTAMP 不同,該函數專門處理標準格式的時間字符串,無需指…

Java 中的排序算法詳解

目錄 一、冒泡排序(Bubble Sort) 原理? 二、選擇排序(Selection Sort) 原理? 三、插入排序(Insertion Sort) 原理? 四、快速排序(Quick Sort) 原理? 五、歸并排序&…