使用ClickHouse快速实现同比、环比分析 ("开窗函数")

简介: ClickHouse的开窗函数

同比、环比分析是一对常见的分析指标,其增长率公式如下:

同比增长率 =(本期数 - 同期数) / 同期数

环比增长率 =(本期数 - 上期数) /上期数

在一些提供了开窗函数的数据库中(如Oracle、Hive),可以利用lag()、lead()函数配合over(),非常方便的实现同比和环比的查询。

大家知道,ClickHose目前是没有提供对应的over()函数的,但是借助一些特殊的函数,也能变相实现开窗的效果。

今天就在此抛砖引玉,向大家介绍如何利用 neighbor 函数,快速实现同比、环比分析。

neighbor函数可以说是lag()与lead()的合体,它可以根据指定的offset,向前或者向后获取到相应字段的值,其完整定义如下所示:

neighbor(column, offset[, default_value])
其中:

column 是指定字段;

offset 是偏移量,例如 1 表示curr_row + 1,即每次向前获取一位;

-1 表示curr_row - 1 ,即每次向后获取一位;

default_value 是默认值,如果curr_row +/- 1 超过了返回结果集的边界,则使用默认值。选填参数,在默认情况下,会使用column字段数据类型的默认值。

现在用一个示例说明,假设有一份销售数据如下所示:

ch7.nauu.com :) WITH toDate('2019-01-01') AS start_date
:-] SELECT
:-]     toStartOfMonth(start_date + (number * 32)) AS date_time,
:-]     (number+1) * 100 AS money
:-] FROM numbers(16);

WITH toDate('2019-01-01') AS start_date
SELECT 
    toStartOfMonth(start_date + (number * 32)) AS date_time, 
    (number + 1) * 100 AS money
FROM numbers(16)

┌──date_time─┬─money─┐
│ 2019-01-01 │   100 │
│ 2019-02-01 │   200 │
│ 2019-03-01 │   300 │
│ 2019-04-01 │   400 │
│ 2019-05-01 │   500 │
│ 2019-06-01 │   600 │
│ 2019-07-01 │   700 │
│ 2019-08-01 │   800 │
│ 2019-09-01 │   900 │
│ 2019-10-01 │  1000 │
│ 2019-11-01 │  1100 │
│ 2019-12-01 │  1200 │
│ 2020-01-01 │  1300 │
│ 2020-02-01 │  1400 │
│ 2020-03-01 │  1500 │
│ 2020-04-01 │  1600 │
└────────────┴───────┘

16 rows in set. Elapsed: 0.002 sec.

这份数据逐月记录了19年1月 至 20年4月的销售额。

现在我们看看 neighbor 函数有什么作用

在刚才的查询中,我们添加neighbor函数,并将offset设为-12,意思是向上取第12行的money值,即取上一年度同月份的money数:

neighbor(money, -12) AS prev_year
再次观察结果:

WITH toDate('2019-01-01') AS start_date
SELECT 
    toStartOfMonth(start_date + (number * 32)) AS date_time, 
    (number + 1) * 100 AS money, 
    neighbor(money, -12) AS prev_year
FROM numbers(16)

┌──date_time─┬─money─┬─prev_year─┐
│ 2019-01-01 │   100 │         0 │ <===================-|
│ 2019-02-01 │   200 │         0 │ <=============-|     |
│ 2019-03-01 │   300 │         0 │ <=======-|     |     |
│ 2019-04-01 │   400 │         0 │ <=-|     |     |     |
│ 2019-05-01 │   500 │         0 │    |     |     |     |
│ 2019-06-01 │   600 │         0 │    |     |     |     |
│ 2019-07-01 │   700 │         0 │    |     |     |     |
│ 2019-08-01 │   800 │         0 │    |     |     |     |
│ 2019-09-01 │   900 │         0 │    |     |     |     |
│ 2019-10-01 │  1000 │         0 │    |     |     |     |
│ 2019-11-01 │  1100 │         0 │    |     |     |     |
│ 2019-12-01 │  1200 │         0 │    |     |     |     |
│ 2020-01-01 │  1300 │       100 │    |     |     |====-|
│ 2020-02-01 │  1400 │       200 │    |     |====-|
│ 2020-03-01 │  1500 │       300 │    |====-|
│ 2020-04-01 │  1600 │       400 │ ==-|
└────────────┴───────┴───────────┘

16 rows in set. Elapsed: 0.002 sec.

可以看到,prev_year即表示同期数。

现在,进一步完善SQL语句,首先按照同比公式计算比率并取整:

round((money-prev_year) / prev_year, 2))
接着,使用-999代号表示没有同比数据的情况:

if(prev_year=0, -999, round((money-prev_year) / prev_year, 2)) AS year_over_year
至此,我们就完成了同比增长率的计算。

接下来看环比计算,与同比类似,只是将offset设置成 -1 即可:

neighbor(money, -1) AS prev_month
此处的prev_month即表示上期数。

所以,最终的SQL语句如下所示:

WITH toDate('2019-01-01') AS start_date
SELECT 
    toStartOfMonth(start_date + (number * 32)) AS date_time, 
    (number + 1) * 100 AS money, 
    neighbor(money, -12) AS prev_year, 
    neighbor(money, -1) AS prev_month, 
    if(prev_year = 0, -999, round((money - prev_year) / prev_year, 2)) AS year_over_year, 
    if(prev_month = 0, -999, round((money - prev_month) / prev_month, 2)) AS month_over_month
FROM numbers(16)

┌──date_time─┬─money─┬─prev_year─┬─prev_month─┬─year_over_year─┬─month_over_month─┐
│ 2019-01-01 │   100 │         0 │          0 │           -999 │             -999 │
│ 2019-02-01 │   200 │         0 │        100 │           -999 │                1 │
│ 2019-03-01 │   300 │         0 │        200 │           -999 │              0.5 │
│ 2019-04-01 │   400 │         0 │        300 │           -999 │             0.33 │
│ 2019-05-01 │   500 │         0 │        400 │           -999 │             0.25 │
│ 2019-06-01 │   600 │         0 │        500 │           -999 │              0.2 │
│ 2019-07-01 │   700 │         0 │        600 │           -999 │             0.17 │
│ 2019-08-01 │   800 │         0 │        700 │           -999 │             0.14 │
│ 2019-09-01 │   900 │         0 │        800 │           -999 │             0.12 │
│ 2019-10-01 │  1000 │         0 │        900 │           -999 │             0.11 │
│ 2019-11-01 │  1100 │         0 │       1000 │           -999 │              0.1 │
│ 2019-12-01 │  1200 │         0 │       1100 │           -999 │             0.09 │
│ 2020-01-01 │  1300 │       100 │       1200 │             12 │             0.08 │
│ 2020-02-01 │  1400 │       200 │       1300 │              6 │             0.08 │
│ 2020-03-01 │  1500 │       300 │       1400 │              4 │             0.07 │
│ 2020-04-01 │  1600 │       400 │       1500 │              3 │             0.07 │
└────────────┴───────┴───────────┴────────────┴────────────────┴──────────────────┘

16 rows in set. Elapsed: 0.006 sec. 

对于这类查询,你有更好的思路或者方法吗? 欢迎和我交流讨论 :P

目录
相关文章
|
2月前
|
存储 监控 数据挖掘
【Clikhouse 探秘】ClickHouse 物化视图:加速大数据分析的新利器
ClickHouse 的物化视图是一种特殊表,通过预先计算并存储查询结果,显著提高查询性能,减少资源消耗,适用于实时报表、日志分析、用户行为分析、金融数据分析和物联网数据分析等场景。物化视图的创建、数据插入、更新和一致性保证通过事务机制实现。
274 14
|
3月前
|
存储 分布式计算 数据库
阿里云国际版设置数据库云分析工作负载的 ClickHouse 版
阿里云国际版设置数据库云分析工作负载的 ClickHouse 版
|
2月前
|
SQL 监控 物联网
ClickHouse在物联网(IoT)中的应用:实时监控与分析
【10月更文挑战第27天】随着物联网(IoT)技术的快速发展,越来越多的设备被连接到互联网上,产生了海量的数据。这些数据不仅包含了设备的状态信息,还包括用户的使用习惯、环境参数等。如何高效地处理和分析这些数据,成为了一个重要的挑战。作为一位数据工程师,我在一个物联网项目中深入使用了ClickHouse,以下是我的经验和思考。
122 0
|
2月前
|
消息中间件 存储 SQL
ClickHouse实时数据处理实战:构建流式分析应用
【10月更文挑战第27天】在数字化转型的大潮中,企业对数据的实时处理需求日益增长。作为一款高性能的列式数据库系统,ClickHouse 在处理大规模数据集方面表现出色,尤其擅长于实时分析。本文将从我个人的角度出发,分享如何利用 ClickHouse 结合 Kafka 消息队列技术,构建一个高效的实时数据处理和分析应用,涵盖数据摄入、实时查询以及告警触发等多个功能点。
131 0
|
7月前
|
存储 SQL 运维
OLAP数据库选型指南:Doris与ClickHouse的深入对比与分析
OLAP数据库选型指南:Doris与ClickHouse的深入对比与分析
|
存储 SQL 数据挖掘
ClickHouse使用场景和案列分析
@[TOC](目录) # 一、ClickHouse 概述 ## 1. ClickHouse简介 ClickHouse 是一款开源的分布式列式数据库,旨在处理大规模数据集并实现快速查询。它最初由俄罗斯搜索引擎公司 Yandex 于 2016 年发布,并在短时间内获得了广泛的关注和应用。ClickHouse 具有高性能、可扩展性和可靠性等特点,成为处理海量数据的理想工具。 ## 2. ClickHouse 发展历程 ClickHouse 的发展历程可以追溯到 2016 年,当时 Yandex 公司意识到传统的关系型数据库在处理大规模数据时存在性能瓶颈,于是开始研发一款专为大数据处理而设计的列式数
2932 0
|
8月前
|
消息中间件 存储 Kafka
基于云数据库ClickHouse 搭建游戏行业用户行为分析系统实践
游戏行业用户流量的引入及长期留存和活跃是衡量游戏商业转化能力的必要条件和重要衡量指标。新游戏投放市场后通常会持续性进行运营推广和迭代优化,需要完善的运营体系来支撑运营。本文重点阐述如何使用云数据库 ClickHouse 作为核心数仓同步离线和实时数据来构建用户分析系统,以及如何通过用户分析系统来分析用户行为常用场景实践案例,指导游戏行业客户构建和使用行为分析系统,达到提高游戏用户留存率和活跃度的目标。
449 0
基于云数据库ClickHouse 搭建游戏行业用户行为分析系统实践
|
SQL 分布式计算 关系型数据库
在SmartBI中使用ClickHouse数据源进行透视分析
在使用SmartBI进行数据分析时,通过MPP高速缓存库可以大大加快计算速度,提高工作效率。我司SmartBI MPP高速缓存库的底层技术为ClickHouse。ClickHouse是一个面向联机分析处理(OLAP)的开源的面向列式存储的数据库管理系统,与Hadoop, Spark相比,ClickHouse很轻量级,由俄罗斯第一大搜索引擎Yandex于2016年6月发布, 开发语言为C++。
1042 0
在SmartBI中使用ClickHouse数据源进行透视分析