You need to enable JavaScript to run this app.
导航
漏斗分析函数
最近更新时间:2025.05.09 19:38:11首次发布时间:2025.05.09 19:38:11
我的收藏
有用
有用
无用
无用

ByteHouse 根据用户行为分析使用场景,定制了漏斗分析函数。相比拼装 SQL或者使用 ClickHouse 原生函数,使用 ByteHouse 自研的专用函数更为高效。本文介绍漏斗分析函数的使用场景,和函数的基本用法。

背景信息

漏斗分析函数可适用于以下业务场景:
选定一段时间范围,观察此时间范围内每一个时间单位(天)内用户按一定时间范围划分的漏斗分层汇总情况。
Image
漏斗计算逻辑简介:

  • 先使用 finderFunnel 计算每个用户在一段时间窗口内的表现;
  • 再使用 funnelRep 聚合 finderFunnel 的结果,形成漏斗每一层所有用户的汇总结果。

函数示意

finderFunnel()

finderFunnel(window, start_timestamp, check_granularity, watch_numbers)(server_timestamp, client_timestamp, check_event1, check_event2...)
  • window:分析观察的窗口总时长时长,单位和client_timestamp 一致,下例中为 86400 *7 秒,也即 7 天。
  • start_timestamp: 分析开始时间戳,如分析从 2022-06-01 开始,所以开始时间戳为 toUInt64(toUnixTimestamp('2022-06-01')) = 1654012800
  • check_granularity: 一个观察步长持续时间,多大粒度内来计算转化分析,单位和client_timestamp 一致,如 1 天则为 86400(单位:秒)。
  • watch_numbers: 观察几个步长,如check_granularity是86400(1 天),watch_numbners = 7,指代从start_timestamp开始观察 7 天每天的漏斗情况
  • server_timestamp:事件发生服务器时间戳列,需转化为UInt64 类型,用于函数运行时,计算事件所属时间槽位/步进。
  • client_timestamp:事件发生客户端时间戳列,需转化为UInt64 类型,用于函数运行时对数据进行排序。
  • check_event: 计算转化的事件列表,在window定义的分析时长范围内满足条件的将会被认为事件触发有效。如有3个事件,则输入:EventName = 'E0001', EventName = 'E0002', EventName = 'E0003'

funnelRep()

使用 funnelRep 聚合 finderFunnel 的结果,形成漏斗每一层所有用户的汇总结果。

funnelRep(number_steps, evnet_count)(funnel_res)
  • number_steps:UInt 型数字,包含的时间槽位数量,通常和 finderFunnel函数中watch_numners保持一致。
  • evnet_count: UInt 型数字,表示事件转化链上事件总数,通常和finderFunnel函数中check_event的时间数量保持一致,
  • funnel_res :转化步骤列表,由 finderFunnel 子查询产生,包含每一个用户产生的所有转化步骤列表。

返回结果:

  • 返回 2 维度数组,输出的二维数组中,总计有 1 个汇总的结果 + 与number_steps 个子数组,第一个子数组是汇总的结果,第二个子数组是第一个时间槽在window定义的分析时长范围内的漏斗计算结果,以此类推。

漏斗分析示例 SQL

示例模型

下面是一张示例用表,是由用户行为事实表 Log 和用户维度表 User 组成常用的星型模型。后文将基于此表为大家演示函数的具体用法。

CREATE TABLE -- 事件日志表
  default.LOG (
    `Visitor` UInt32,
    `EventName` String,
    `EventTime` DateTime,
    `Province` String,
    `City` String
  ) ENGINE = CnchMergeTree
  ORDER BY Visitor;
  
  CREATE TABLE -- 用户表
  default.User (
    `Visitor` UInt32,
    `Fvisit_Time` DateTime,
    `Fvisit_Province` String,
    `Fvisit_City` String
  ) ENGINE = CnchMergeTree
  ORDER BY Visitor;

使用示例

以下示例指代返回 从 2022/6/1-2022/6/8 的 7 天中, 'E0001', 'E0002', 'E0003' 3 个事件的转化漏斗:

SELECT funnelRep(7, 3)(funnel_res)
FROM
(
    SELECT finderFunnel(7 * 86400, 1654012800, 86400, 7)(toUInt64(toUnixTimestamp(LOG.EventTime)), toUInt64(toUnixTimestamp(LOG.EventTime)), LOG.EventName = 'E0001', LOG.EventName = 'E0002', LOG.EventName = 'E0003') AS funnel_res
    FROM LOG
    LEFT JOIN
    (
        SELECT *
        FROM User AS t
    ) AS U ON LOG.Visitor = U.Visitor
    WHERE (EventTime >= '2022-06-01 00:00:00') AND (EventTime <'2022-06-08 00:00:00') AND (EventName IN ('E0001', 'E0002', 'E0003'))
    GROUP BY Visitor
)
SETTINGS distributed_product_mode = 'local', distributed_group_by_no_merge = 1

上面的示例 SQL 返回为

┌─funnelRep(7, 3)(funnel_res)─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ [[5994501,5944849,56423],[3791527,3780488,39431],[3792876,3767458,33024],[3792031,3733089,26709],[3791519,3656585,20668],[3791859,3480158,14385],[3793389,3077233,8691],[3792344,2143108,3641]] │
  • 即整体漏斗(E0001->E0002->E0003)为:[5994501,5944849,56423]
  • 第 1 天的漏斗为:[3791527,3780488,39431]
  • ...
  • 第 7 天的漏斗:[3792344,2143108,3641]