漏斗分析函數與留存函數
在數據分析中,漏斗分析是衡量和優化用戶在特定流程中的轉化率的重要工具,留存分析則用于衡量用戶對產品或服務的持續使用程度,這兩者都是衡量產品健康度和用戶滿意度的重要指標。漏斗分析函數與留存函數是專門為了處理和分析這類數據而設計,旨在簡化查詢過程,提高效率。本文將為您介紹漏斗分析函數和留存函數的使用方法和應用場景。
背景信息
事件(Event)代表了用戶的某個或一系列有意義的行為,比如游戲App的下載、注冊、登錄等,通過分析用戶的各項行為數據還原用戶真實的使用過程,從而提升產品轉化率,助力業務增長。常見的用戶行為分析包括事件分析、漏斗分析、留存分析等,其中漏斗和留存是最常見的用戶行為分析場景:
漏斗分析:是一種用來分析用戶在指定階段轉化情況的分析模型,可以分析用戶在各個階段的行為轉化率,然后通過轉化率來衡量每一個階段的表現,從而助力產品進行針對化的優化,提升轉化率。
留存分析:是一種用來分析用戶參與情況或活躍程度的分析模型,考察初始行為的用戶中有多少會進行后續行為,從而衡量產品對用戶的價值。
漏斗分析函數
函數定義
漏斗分析常針對一系列預定義的步驟,計算用戶從第一步到最后一步的完成率。具體的做法為搜索滑動時間窗口內的事件列表,計算條件匹配的事件鏈里的最大連續事件數。該函數遵循以下規則:
從事件鏈中的第一個條件開始判斷。如果數據中包含符合條件的事件,則向計數器加1,并以此事件對應的時間作為滑動窗口的起始時間。如果未能找到符合第一個條件的數據,則返回為0。
在滑動窗口內,如果事件鏈中的事件按順序發生,則計數器遞增。如果超出了時間窗口,則計數器不再增加。
如有多條符合條件的事件鏈,則輸出最長的事件鏈。
函數語法
SELECT windowFunnel(time_frame, mode, time, ARRAY[Cond1,Cond2,...CondN])
FROM tbl
GROUP BY uid;
參數說明
參數 | 說明 |
time_frame | 滑動窗口的大小,類型為bigint。 單位默認為s。 |
mode | 事件鏈的篩選模式,類型為text。取值范圍:"default", "strict"。 默認值為default,表示執行一般的漏斗計算。 模式為strict時表示deduplication模式,即篩選出的事件鏈不能有重復的事件。假設array參數為[event_type='A',event_type='B',event_type='C',event='D'],原事件鏈為 "A-B-C-B-D"。由于事件B重復,那么篩選出的事件鏈只能是 "A-B-C"。 |
time | 包含時間戳的列。目前支持timestamp類型。 |
array[Cond1,Cond2,...CondN] | 定義的事件鏈,類型為array。 |
返回值說明
返回bigint
類型的值,值為滑動窗口內滿足條件的最大連續事件數。
使用示例
在進行漏斗分析和留存分析之前,應確保事件數據的準確性和完整性。以下為分析用戶從瀏覽網頁到下訂單事件的SQL示例。
CREATE TABLE action
(
uid INT,
event_type TEXT,
time TIMESTAMP
);
INSERT INTO action
VALUES (1, 'Browse', '2020-01-02 11:00:00');
INSERT INTO action
VALUES (1, 'Click', '2020-01-02 11:10:00');
INSERT INTO action
VALUES (1, 'Order', '2020-01-02 11:20:00');
INSERT INTO action
VALUES (1, 'Pay', '2020-01-02 11:30:00');
INSERT INTO action
VALUES (1, 'Browse', '2020-01-02 11:00:00');
INSERT INTO action
VALUES (1, 'Browse', '2020-01-02 11:00:00');
INSERT INTO action
VALUES (2, 'Order', '2020-01-02 11:00:00');
INSERT INTO action
VALUES (2, 'Pay', '2020-01-02 11:10:00');
INSERT INTO action
VALUES (3, 'Browse', '2020-01-02 11:20:00');
INSERT INTO action
VALUES (3, 'Click', '2020-01-02 12:00:00');
INSERT INTO action
VALUES (4, 'Browse', '2020-01-02 11:50:00');
INSERT INTO action
VALUES (4, 'Click', '2020-01-02 12:00:00');
INSERT INTO action
VALUES (5, 'Browse', '2020-01-02 11:50:00');
INSERT INTO action
VALUES (5, 'Click', '2020-01-02 12:00:00');
INSERT INTO action
VALUES (5, 'Order', '2020-01-02 11:10:00');
INSERT INTO action
VALUES (6, 'Browse', '2020-01-02 11:50:00');
INSERT INTOaction
VALUES (6, 'Click', '2020-01-02 12:00:00');
INSERT INTO action
VALUES (6, 'Order', '2020-01-02 12:10:00');
漏斗函數可以幫助您分析每個用戶對應事件窗口下所達到的事件程度,這里指定完成一條完整的事件流程度為4。如下所示SQL語句為查詢不同用戶對應的事件程度。
查詢用戶事件
SELECT uid,
windowFunnel(1800, 'default',
TIME,
ARRAY [event_type = 'Browse', event_type = 'Click',
event_type = 'Order', event_type = 'Pay']) AS level
FROM action
GROUP BY uid
ORDER BY uid
返回結果
uid | level
-----+-------
1 | 4
2 | 0
3 | 1
4 | 2
5 | 2
6 | 3
(6 ROWS)
留存函數
函數定義
留存函數用于計算一段時間內的用戶留存情況。該函數接收1到31個條件,從第一個條件開始判斷事件是否滿足條件,如果滿足條件則輸出 1,不滿足則輸出0,最終返回0和1的數組。通過統計結果為1的數據,計算用戶留存率。
函數語法
留存函數的語法如下。
SELECT retention(ARRAY[Cond1,...CondN]) FROM tbl;
參數說明
參數 | 說明 |
array[Conds] | 條件表達式組成的數組,類型為array,數組內最多支持傳入31個條件,多個條件用逗號隔開。 |
返回值說明
返回包含0和1的數組。數組里0和1的個數與傳入的條件數一致。從數組的第一個條件開始依次判斷:
如果事件滿足當前條件,則輸出1。
如果事件不滿足當前條件,則當前位置及之后的所有位置均為0。
使用示例
在進行漏斗分析和留存分析之前,應確保事件數據的準確性和完整性。以下為創建數據集并分析用戶購買事件的SQL示例。
CREATE TABLE retention_test
(
id INTEGER,
action text,
time TIMESTAMP
);
INSERT INTO retention_test
VALUES (1, 'pv', '2022-01-01 08:00:05'),
(2, 'pv', '2022-01-01 10:20:08'),
(1, 'buy', '2022-01-02 15:30:10'),
(2, 'pv', '2022-01-02 17:30:05'),
(3, 'buy', '2022-01-01 05:30:09'),
(3, 'buy', '22022-01-02 08:10:15'),
(4, 'pv', '2022-01-02 21:09:15'),
(5, 'pv', '2022-01-01 22:10:53'),
(5, 'pv', '2022-01-02 19:10:52'),
(5, 'buy', '2022-01-02 20:00:50');
以下為查詢在2022-01-01訪問產品頁面,并且在之后一天2022-01-02進行購買的用戶明細和查詢結果。
查詢用戶購買明細
SELECT id,
retention(ARRAY [action = 'pv' AND time::date = '2022-01-01', action = 'buy' AND time::date = '2022-01-02']) AS retention
FROM retention_test
GROUP BY id
ORDER BY id;
查詢結果
id | retention
----+-----------
1 | {1,1}
2 | {1,0}
3 | {0,0}
4 | {0,0}
5 | {1,1}
(5 ROWS)
對用戶購買事件的統計查詢和查詢結果如下。
用戶事件統計查詢
SELECT SUM(r[1]) AS day1, SUM(r[2]) AS day2
FROM (SELECT id,
retention(ARRAY [action = 'pv' AND time::date = '2022-01-01',
action = 'buy' AND time::date = '2022-01-02']) AS r
FROM retention_test
GROUP BY id
ORDER BY id) t;
查詢結果
day1 | day2
------+-----
3 | 2
(1 ROW)
留存擴展函數
函數定義
留存分析是最常見的典型用戶增長分析場景,用戶經常需要繪制數據可視化圖形,分析用戶的留存情況?;谠搱鼍埃?span id="6f4f8d67c3t9d" outputclass="productName" data-tag="ph" data-ref-searchable="yes" data-reuse-tag="productName" data-type="productName" data-product-code="gpdb" docid="4265570" class="ph productName">云原生數據倉庫 AnalyticDB PostgreSQL 版提供了range_retention_count和range_retention_sum兩個函數用于服務該場景。
range_retention_count:用于記錄每個用戶的留存情況,返回值為bigint數組??梢宰鳛?b>range_retention_sum的輸入值。
range_retention_sum:用于統計所有用戶每天的留存率。返回值為text數組。
函數語法
range_retention_count
range_retention_count(is_first, is_active, dt, retention_intervals, retention_granularity)
range_retention_sum
range_retention_sum(range_retention_count)
參數說明
參數 | 類型 | 說明 |
is_first | boolean | 是否符合初始行為。
|
is_active | boolean | 是否符合后續留存行為。
|
dt | date | 發生行為的日期。如2020-12-12。 |
retention_interval | int[] | 留存間隔,最多支持15個留存間隔。 例如:array[1,3,5,7,15,30]。 |
retention_granularity | text | 留存粒度,目前僅支持day。 |
range_retention_count使用示例
以下兩個SQL示例可以獲知range_retention_count返回的每個用戶在對應時間t,t+1,t+2的留存情況,使用示例如下。
準備數據集
CREATE TABLE event_tbl(uid INT, event TEXT, dt DATE);
INSERT INTO event_tbl VALUES
(1, 'pay', '2022-05-01'),(1, 'login', '2022-05-01'),
(1, 'pay', '2022-05-02'),(1, 'login', '2022-05-02'),
(2, 'login', '2022-05-01'),
(3, 'login', '2022-05-02'), (3, 'pay', '2022-05-03'),
(3, 'pay', '2022-05-04');
計算用戶留存明細
SELECT
uid, r
FROM
(
SELECT
uid,
range_retention_count(event = 'login', event = 'pay', dt,
ARRAY [1, 2], 'day') AS r
FROM
event_tbl
GROUP BY
uid
) AS t
ORDER BY
uid;
查詢明細
uid | r
-----+-----------------------------
1 | {"{8156,1,0}","{8157,0,0}"}
2 | {"{8156,0,0}"}
3 | {"{8157,1,1}"}
(3 ROWS)
查詢日期
SELECT to_date(8156)
to_date
------------
2022-05-01
range_retention_sum使用示例
range_retention_sum以range_retention_count的結果作為輸入,使用示例如下。
計算留存率
WITH retention_count_info AS (
SELECT
uid,
range_retention_count(event = 'login', event = 'pay',
dt, array[1, 2], 'day') AS info
FROM
event_tbl
GROUP BY
uid
), retention_sum AS (
SELECT regexp_split_to_array(unnest(range_retention_sum(info)), ',') AS s
FROM retention_count_info
) SELECT to_date(s[1]::int) AS login_date,
s[3]::numeric / s[2]::numeric AS retention_d1,
s[4]::numeric / s[2]::numeric AS retention_d2
FROM retention_sum
ORDER BY login_date;
查詢結果
login_date | retention_d1 | retention_d2
------------+------------------------+------------------------
2022-05-01 | 0.50000000000000000000 | 0.00000000000000000000
2022-05-02 | 0.50000000000000000000 | 0.50000000000000000000
(2 ROWS)