如何充分发挥 SQL 能力

简介: MaxCompute(ODPS)SQL 发展到今天已经颇为成熟,作为一种 SQL 方言,可以高效地应用在各种数据处理场景。本文尝试独辟蹊径,强调通过灵活的、发散性的数据处理思维,就可以用最基础的语法,解决复杂的数据场景。

1.前言



1.1 初衷


如何高效地使用 MaxCompute(ODPS)SQL ,将基础 SQL 语法运用到极致。

在大数据如此流行的今天,不只是专业的数据人员,需要经常地跟 SQL 打交道,即使是产品、运营等非技术同学,也会或多或少地使用到 SQL ,如何高效地发挥 SQL 的能力,继而发挥数据的能力,变得尤为重要。MaxCompute(ODPS)SQL 发展到今天已经颇为成熟,作为一种 SQL 方言,其 SQL 语法支持完备,具有非常丰富的内置函数,支持开窗函数、用户自定义函数、用户自定义类型等诸多高级特性,可以高效地应用在各种数据处理场景。如何充分发挥 SQL 能力,是本篇文章的主题。本文尝试独辟蹊径,强调通过灵活的、发散性的数据处理思维,就可以用最基础的语法,解决复杂的数据场景。

1.2 适合人群


不论是初学者还是资深人员,本篇文章或许都能有所帮助,不过更适合中级、高级读者阅读。

本篇文章重点介绍数据处理思维,并没有涉及到过多高阶的语法,同时为了避免主题发散,文中涉及的函数、语法特性等,不会花费篇幅进行专门的介绍,读者可以按自身情况自行了解。

1.3 内容结构


本篇文章将围绕数列生成、区间变换、排列组合、连续判别等主题进行介绍,并附以案例进行实际运用讲解。每个主题之间有轻微的前后依赖关系,依次阅读更佳。

1.4 提示信息


本篇文章涉及的 SQL 语句只使用到了 MaxCompute(ODPS)SQL 基础语法特性,理论上所有 SQL 均可以在当前最新版本中运行,同时特意注明,运行环境、兼容性等问题不在本篇文章关注范围内。


2.数列


数列是最常见的数据形式之一,实际数据开发场景中遇到的基本都是有限数列。本节将从最简单的递增数列开始,找出一般方法并推广到更泛化的场景。

2.1 常见数列

2.1.1 一个简单的递增数列

首先引出一个简单的递增整数数列场景:

  • 从数值 0 开始;
  • 之后的每个数值递增 1
  • 至数值 3 结束;

如何生成满足以上三个条件的数列?[0,1,2,3]

实际上,生成该数列的方式有多种,此处介绍其中一种简单且通用的方案。


-- SQL - 1select    t.pos as a_nfrom (    select posexplode(split(space(3), space(1), false))) t;

通过上述 SQL 片段可得知,生成一个递增序列只需要三个步骤:

1)生成一个长度合适的数组,数组中的元素不需要具有实际含义;2)通过 UDTF 函数 posexplode 对数组中的每个元素生成索引下标;

3)取出每个元素的索引下标。以上三个步骤可以推广至更一般的数列场景:等差数列、等比数列。下文将以此为基础,直接给出最终实现模板。

2.1.2 等差数列

若设首项 ,公差为 ,则等差数列的通项公式为

SQL 实现:


-- SQL - 2select    a + t.pos * d as a_nfrom (    select posexplode(split(space(n - 1), space(1), false))) t;

2.1.3 等比数列

若设首项 ,公比为 ,则等比数列的通项公式为  

SQL 实现:


-- SQL - 3select    a * pow(q, t.pos) as a_nfrom (    select posexplode(split(space(n - 1), space(1), false))) t;

提示:亦可直接使用 MaxCompute(ODPS)系统函数 sequence 快速生成数列。


-- SQL - 4select sequence(1, 3, 1);
-- result[1, 2, 3]

2.2 应用场景举例


2.2.1 还原任意维度组合下的维度列簇名称


在多维分析场景下,可能会用到高阶聚合函数,如 cuberollupgrouping sets 等,可以针对不同维度组合下的数据进行聚合统计。

场景描述

现有用户访问日志表 visit_log ,每一行数据表示一条用户访问日志。


-- SQL - 5with visit_log as (    select stack (        6,        '2024-01-01', '101', '湖北', '武汉', 'Android',        '2024-01-01', '102', '湖南', '长沙', 'IOS',        '2024-01-01', '103', '四川', '成都', 'Windows',        '2024-01-02', '101', '湖北', '孝感', 'Mac',        '2024-01-02', '102', '湖南', '邵阳', 'Android',        '2024-01-03', '101', '湖北', '武汉', 'IOS'    )     -- 字段:日期,用户,省份,城市,设备类型    as (dt, user_id, province, city, device_type))select * from visit_log;

现针对省份 province , 城市 city, 设备类型 device_type 三个维度列,通过 grouping sets 聚合统计得到了不同维度组合下的用户访问量。问:1)如何知道一条统计结果是根据哪些维度列聚合出来的?

2)想要输出 聚合的维度列的名称,用于下游的报表展示等场景,又该如何处理?

解决思路

可以借助 MaxCompute(ODPS)提供的 GROUPING__ID 来解决,核心方法是对 GROUPING__ID 进行逆向实现。 



详细步骤如下:

一、准备好所有的 GROUPING__ID 。

生成一个包含 个数值的递增数列,将每个数值转为 2 进制字符串,并展开该 2 进制字符串的每个比特位。

GROUPING__ID

bits

0

{ ..., 0, 0, 0 }

1

{ ..., 0, 0, 1 }

2

{ ..., 0, 1, 0 }

3

{ ..., 0, 1, 1 }

...

...



2n2n




...

其中 为所有维度列的数量, 即为所有维度组合的数量,每个数值表示一种 GROUPING__ID。

二、准备好所有维度名称。

生成一个字符串序列,依次保存 个维度列的名称,即


{ dim_name_1, dim_name_2, ..., dim_name_n }

三、将 GROUPING__ID 映射到维度列名称。

对于 GROUPING__ID 递增数列中的每个数值,将该数值的 2 进制每个比特位与维度名称序列的下标进行映射,输出所有对应比特位 0 的维度名称。例如:


GROUPING__ID:3 => { 0, 1, 1 }维度名称序列:{ 省份, 城市, 设备类型 }
映射:{ 0:省份, 1:城市, 1:设备类型 }
GROUPING__ID 为 3 的数据行聚合维度即为:省份

SQL 实现


-- SQL - 6with group_dimension as (    select -- 每种分组对应的维度字段        gb.group_id, concat_ws(",", collect_list(case when gb.placeholder_bit = 0 then dim_col.val else null end)) as dimension_name    from (        select groups.pos as group_id, pe.*        from (            select posexplode(split(space(cast(pow(2, 3) as int) - 1), space(1), false))        ) groups -- 所有分组        lateral view posexplode(regexp_extract_all(lpad(conv(groups.pos,10,2), 3, "0"), '(0|1)')) pe as placeholder_idx, placeholder_bit -- 每个分组的bit信息    ) gb    left join ( -- 所有维度字段        select posexplode(split("省份,城市,设备类型", ','))    ) dim_col on gb.placeholder_idx = dim_col.pos    group by gb.group_id)select     group_dimension.dimension_name,    province, city, device_type,    visit_countfrom (    select        grouping_id(province, city, device_type) as group_id,        province, city, device_type,        count(1) as visit_count    from visit_log b    group by province, city, device_type    GROUPING SETS(        (province),        (province, city),        (province, city, device_type)    )) tjoin group_dimension on t.group_id = group_dimension.group_idorder by group_dimension.dimension_name;

dimension_name

province

city

device_type

visit_count

省份

湖北

NULL

NULL

3

省份

湖南

NULL

NULL

2

省份

四川

NULL

NULL

1

省份,城市

湖北

武汉

NULL

2

省份,城市

湖南

长沙

NULL

1

省份,城市

湖南

邵阳

NULL

1

省份,城市

湖北

孝感

NULL

1

省份,城市

四川

成都

NULL

1

省份,城市,设备类型

湖北

孝感

Mac

1

省份,城市,设备类型

湖南

长沙

IOS

1

省份,城市,设备类型

湖南

邵阳

Android

1

省份,城市,设备类型

四川

成都

Windows

1

省份,城市,设备类型

湖北

武汉

Android

1

省份,城市,设备类型

湖北

武汉

IOS

1




3.区间


区间相较数列具有不同的数据特征,不过在实际应用中,数列与区间的处理具有较多相通性。本节将介绍一些常见的区间场景,并抽象出通用的解决方案。

3.1 常见区间操作


3.1.1 区间分割

已知一个数值区间 ,如何将该区间均分成 段子区间?

该问题可以简化为数列问题,数列公式为 其中 具体步骤如下

1)生成一个长度为 的数组;2)通过 UDTF 函数 posexplode 对数组中的每个元素生成索引下标;

3)取出每个元素的索引下标,并进行数列公式计算,得出每个子区间的起始值与结束值。

SQL 实现:


-- SQL - 7select    a + t.pos * d as sub_interval_start, -- 子区间起始值    a + (t.pos + 1) * d as sub_interval_end -- 子区间结束值from (    select posexplode(split(space(n - 1), space(1), false))) t;

3.1.2 区间交叉

已知两个日期区间存在交叉 ['2024-01-01', '2024-01-03'] 、 ['2024-01-02', '2024-01-04']。问:

1)如何合并两个日期区间,并返回合并后的新区间?

2)如何知道哪些日期是交叉日期,并返回该日期交叉次数?

解决上述问题的方法有多种,此处介绍其中一种简单且通用的方案。核心思路是结合数列生成、区间分割方法,先将日期区间分解为最小处理单元,即多个日期组成的数列,然后再基于日期粒度做统计。具体步骤如下:

1)获取每个日期区间包含的天数;2)按日期区间包含的天数,将日期区间拆分为相应数量的递增日期序列;

3)通过日期序列统计合并后的区间,交叉次数。

SQL 实现:


-- SQL - 8with dummy_table as (    select stack(        2,        '2024-01-01', '2024-01-03',        '2024-01-02', '2024-01-04'    ) as (date_start, date_end))select     min(date_item) as date_start_merged,     max(date_item) as date_end_merged,     collect_set( -- 交叉日期计数        case when date_item_cnt > 1 then concat(date_item, ':', date_item_cnt) else null end    ) as overlap_datefrom (    select         -- 拆解后的单个日期        date_add(date_start, pos) as date_item,        -- 拆解后的单个日期出现的次数        count(1) over (partition by date_add(date_start, pos)) as date_item_cnt    from dummy_table    lateral view posexplode(split(space(datediff(date_end, date_start)), space(1), false)) t as pos, val) t;

date_start_merged

date_end_merged

overlap_date

2024-01-01

2024-01-04

["2024-01-02:2","2024-01-03:2"]


🤔增加点儿难度!

如果有多个日期区间,且区间之间交叉状态未知,上述问题又该如何求解。即:

1)如何合并多个日期区间,并返回合并后的多个新区间?

2)如何知道哪些日期是交叉日期,并返回该日期交叉次数?

SQL 实现:


-- SQL - 9with dummy_table as (    select stack(        5,        '2024-01-01', '2024-01-03',        '2024-01-02', '2024-01-04',        '2024-01-06', '2024-01-08',        '2024-01-08', '2024-01-08',        '2024-01-07', '2024-01-10'    ) as (date_start, date_end))select    min(date_item) as date_start_merged,     max(date_item) as date_end_merged,    collect_set( -- 交叉日期计数        case when date_item_cnt > 1 then concat(date_item, ':', date_item_cnt) else null end    ) as overlap_datefrom (    select         -- 拆解后的单个日期        date_add(date_start, pos) as date_item,        -- 拆解后的单个日期出现的次数        count(1) over (partition by date_add(date_start, pos)) as date_item_cnt,        -- 对于拆解后的单个日期,重组为新区间的标记        date_add(date_add(date_start, pos), 1 - dense_rank() over (order by date_add(date_start, pos))) as cont    from dummy_table    lateral view posexplode(split(space(datediff(date_end, date_start)), space(1), false)) t as pos, val) tgroup by cont;

date_start_merged

date_end_merged

overlap_date

2024-01-01

2024-01-04

["2024-01-02:2","2024-01-03:2"]

2024-01-06

2024-01-10

["2024-01-07:2","2024-01-08:3"]

3.2 应用场景举例

3.2.1 按任意时段统计数据

场景描述

现有用户还款计划表 user_repayment ,该表内的一条数据,表示用户在指定日期区间内 [date_start, date_end] ,每天还款 repayment 元。


-- SQL - 10with user_repayment as (    select stack(        3,        '101', '2024-01-01', '2024-01-15', 10,        '102', '2024-01-05', '2024-01-20', 20,        '103', '2024-01-10', '2024-01-25', 30    )     -- 字段:用户,开始日期,结束日期,每日还款金额    as (user_id, date_start, date_end, repayment))select * from user_repayment;

如何统计任意时段内(如:2024-01-15至2024-01-16)每天所有用户的应还款总额?

解决思路

核心思路是将日期区间转换为日期序列,再按日期序列进行汇总统计。

SQL 实现


-- SQL - 11select     date_item as day,     sum(repayment) as total_repaymentfrom (    select         date_add(date_start, pos) as date_item,        repayment    from user_repayment    lateral view posexplode(split(space(datediff(date_end, date_start)), space(1), false)) t as pos, val) twhere date_item >= '2024-01-15' and date_item <= '2024-01-16'group by date_itemorder by date_item;

day

total_repayment

2024-01-15

60

2024-01-16

50




4.排列组合


排列组合是针对离散数据常用的数据组织方法,本节将分别介绍排列、组合的实现方法,并结合实例着重介绍通过组合对数据的处理。

4.1 常见排列组合操作


4.1.1 排列

已知字符序列 [ 'A', 'B', 'C' ] ,每次从该序列中可重复地选取出 2 个字符,如何获取到所有的排列?

借助多重 lateral view 即可解决,整体实现比较简单。


-- SQL - 12select     concat(val1, val2) as permfrom (select split('A,B,C', ',') as characters) dummylateral view explode(characters) t1 as val1lateral view explode(characters) t2 as val2;

perm

AA

AB

AC

BA

BB

BC

CA

CB

CC

4.1.2 组合

已知字符序列 [ 'A', 'B', 'C' ] ,每次从该序列中可重复地选取出 2 个字符,如何获取到所有的组合?

借助多重 lateral view 即可解决,整体实现比较简单。


-- SQL - 13select     concat(least(val1, val2), greatest(val1, val2)) as combfrom (select split('A,B,C', ',') as characters) dummylateral view explode(characters) t1 as val1lateral view explode(characters) t2 as val2group by least(val1, val2), greatest(val1, val2);

comb

AA

AB

AC

BB

BC

CC


提示:亦可直接使用 MaxCompute(ODPS)系统函数 combinations 快速生成组合。


-- SQL - 14select combinations(array('foo', 'bar', 'boo'),2);
-- result[['foo', 'bar'], ['foo', 'boo']['bar', 'boo']]

4.2 应用场景举例


4.2.1 分组对比统计

场景描述

现有投放策略转化表,该表内的一条数据,表示一天内某投放策略带来的订单量。


-- SQL - 15with strategy_order as (    select stack(        3,        '2024-01-01', 'Strategy A', 10,        '2024-01-01', 'Strategy B', 20,        '2024-01-01', 'Strategy C', 30    )     -- 字段:日期,投放策略,单量    as (dt, strategy, order_cnt))select * from strategy_order;

如何按投放策略建立两两对比组,按组对比展示不同策略转化单量情况?

对比组

投放策略

转化单量

Strategy A-Strategy B

Strategy A

xxx

Strategy A-Strategy B

Strategy B

xxx


解决思路

核心思路是从所有投放策略列表中不重复地取出 2 个策略,生成所有的组合结果,然后关联 strategy_order 表分组统计结果。

SQL 实现


-- SQL - 16select /*+ mapjoin(combs) */    combs.strategy_comb,    so.strategy,    so.order_cntfrom strategy_order sojoin ( -- 生成所有对比组    select         concat(least(val1, val2), '-', greatest(val1, val2)) as strategy_comb,        least(val1, val2) as strategy_1, greatest(val1, val2) as strategy_2    from (        select collect_set(strategy) as strategies        from strategy_order    ) dummy    lateral view explode(strategies) t1 as val1    lateral view explode(strategies) t2 as val2    where val1 <> val2    group by least(val1, val2), greatest(val1, val2)) combs on 1 = 1where so.strategy in (combs.strategy_1, combs.strategy_2)order by combs.strategy_comb, so.strategy;

对比组

投放策略

转化单量

Strategy A-Strategy B

Strategy A

10

Strategy A-Strategy B

Strategy B

20

Strategy A-Strategy C

Strategy A

10

Strategy A-Strategy C

Strategy C

30

Strategy B-Strategy C

Strategy B

20

Strategy B-Strategy C

Strategy C

30




5.连续


本节主要介绍连续性问题,重点描述了常见连续活跃场景。对于静态类型的连续活跃、动态类型的连续活跃,分别阐述了不同的实现方案。


5.1 普通连续活跃统计

场景描述

现有用户访问日志表 visit_log ,每一行数据表示一条用户访问日志。


-- SQL - 17with visit_log as (    select stack (        6,        '2024-01-01', '101', '湖北', '武汉', 'Android',        '2024-01-01', '102', '湖南', '长沙', 'IOS',        '2024-01-01', '103', '四川', '成都', 'Windows',        '2024-01-02', '101', '湖北', '孝感', 'Mac',        '2024-01-02', '102', '湖南', '邵阳', 'Android',        '2024-01-03', '101', '湖北', '武汉', 'IOS'    )     -- 字段:日期,用户,省份,城市,设备类型    as (dt, user_id, province, city, device_type))select * from visit_log;

如何获取连续访问大于或等于 2 天的用户?

上述问题在分析连续性时,获取连续性的结果以超过固定阈值为准,此处归类为 连续活跃大于 N 天阈值的普通连续活跃场景统计

SQL 实现

基于相邻日期差实现( lag / lead 版)

整体实现比较简单。


-- SQL - 18select user_idfrom (    select         *,        lag(dt, 2 - 1) over (partition by user_id order by dt) as lag_dt    from (select dt, user_id from visit_log group by dt, user_id) t0) t1where datediff(dt, lag_dt) + 1 = 2group by user_id;

user_id

101

102

基于相邻日期差实现(排序版)

整体实现比较简单。


-- SQL - 19select user_idfrom (    select *,         dense_rank() over (partition by user_id order by dt) as dr    from visit_log) t1where datediff(dt, date_add(dt, 1 - dr)) + 1 = 2group by user_id;

user_id

101

102

基于连续活跃天数实现

可以视作 基于相邻日期差实现(排序版) 的衍生版本,该实现能获取到更多信息,如连续活跃天数。


-- SQL - 20select user_idfrom (    select         *,        -- 连续活跃天数        count(distinct dt)             over (partition by user_id, cont) as cont_days    from (        select             *,             date_add(dt, 1 - dense_rank()                 over (partition by user_id order by dt)) as cont        from visit_log    ) t1) t2where cont_days >= 2group by user_id;

user_id

101

102

基于连续活跃区间实现

可以视作 基于相邻日期差实现(排序版) 的衍生版本,该实现能获取到更多信息,如连续活跃区间。


-- SQL - 21select user_idfrom (    select         user_id, cont,         -- 连续活跃区间        min(dt) as cont_date_start, max(dt) as cont_date_end    from (        select             *,             date_add(dt, 1 - dense_rank()                 over (partition by user_id order by dt)) as cont        from visit_log    ) t1    group by user_id, cont) t2where datediff(cont_date_end, cont_date_start) + 1 >= 2group by user_id;

user_id

101

102

5.2 动态连续活跃统计

场景描述

现有用户访问日志表 visit_log ,每一行数据表示一条用户访问日志。


-- SQL - 22with visit_log as (    select stack (        6,        '2024-01-01', '101', '湖北', '武汉', 'Android',        '2024-01-01', '102', '湖南', '长沙', 'IOS',        '2024-01-01', '103', '四川', '成都', 'Windows',        '2024-01-02', '101', '湖北', '孝感', 'Mac',        '2024-01-02', '102', '湖南', '邵阳', 'Android',        '2024-01-03', '101', '湖北', '武汉', 'IOS'    )     -- 字段:日期,用户,省份,城市,设备类型    as (dt, user_id, province, city, device_type))select * from visit_log;

如何获取最长的 2 个连续活跃用户,输出用户、最长连续活跃天数、最长连续活跃日期区间?

上述问题在分析连续性时,获取连续性的结果不是且无法与固定的阈值作比较,而是各自以最长连续活跃作为动态阈值,此处归类为 动态连续活跃场景统计

SQL 实现

基于 普通连续活跃场景统计 的思路进行扩展即可,此处直接给出最终 SQL :



-- SQL - 23select    user_id,     -- 最长连续活跃天数    datediff(max(dt), min(dt)) + 1 as cont_days,    -- 最长连续活跃日期区间    min(dt) as cont_date_start, max(dt) as cont_date_endfrom (    select         *,         date_add(dt, 1 - dense_rank()             over (partition by user_id order by dt)) as cont    from visit_log) t1group by user_id, contorder by cont_days desclimit 2;

user_id

cont_days

cont_date_start

cont_date_end

101

3

2024-01-01

2024-01-03

102

2

2024-01-01

2024-01-02



6.扩展


引申出更复杂的场景,是本篇文章前面章节内容的结合与变种。

6.1 区间连续(最长子区间切分)


场景描述

现有用户扫描或连接 WiFi 记录表 user_wifi_log ,每一行数据表示某时刻用户扫描或连接 WiFi 的日志。



-- SQL - 24with user_wifi_log as (    select stack (        9,        '2024-01-01 10:01:00', '101', 'cmcc-Starbucks', 'scan', -- 扫描        '2024-01-01 10:02:00', '101', 'cmcc-Starbucks', 'scan',        '2024-01-01 10:03:00', '101', 'cmcc-Starbucks', 'scan',        '2024-01-01 10:04:00', '101', 'cmcc-Starbucks', 'conn', -- 连接        '2024-01-01 10:05:00', '101', 'cmcc-Starbucks', 'conn',        '2024-01-01 10:06:00', '101', 'cmcc-Starbucks', 'conn',        '2024-01-01 11:01:00', '101', 'cmcc-Starbucks', 'conn',        '2024-01-01 11:02:00', '101', 'cmcc-Starbucks', 'conn',        '2024-01-01 11:03:00', '101', 'cmcc-Starbucks', 'conn'    )     -- 字段:时间,用户,WiFi,状态(扫描、连接)    as (time, user_id, wifi, status))select * from user_wifi_log;

现需要进行用户行为分析,如何划分用户不同 WiFi 行为区间?满足:1)行为类型分为两种:连接(scan)、扫描(conn);2)行为区间的定义为:相同行为类型,且相邻两次行为的时间差不超过 30 分钟;

3)不同行为区间在满足定义的情况下应取到最长;

user_id

wifi

status

time_start

time_end

备注

101

cmcc-Starbucks

scan

2024-01-01 10:01:00

2024-01-01 10:03:00

用户扫描了 WiFi

101

cmcc-Starbucks

conn

2024-01-01 10:04:00

2024-01-01 10:06:00

用户连接了 WiFi

101

cmcc-Starbucks

conn

2024-01-01 11:01:00

2024-01-01 11:02:00

距离上次连接已经超过 30 分钟,认为是一次新的连接行为


上述问题稍显复杂,可视作
动态连续活跃统计 中介绍的 最长连续活跃 的变种。可以描述为 结合连续性阈值与行为序列中的上下文信息,进行最长子区间的划分 的问题


SQL 实现

核心逻辑:以用户、WIFI 分组,结合连续性阈值与行为序列上下文信息,划分行为区间。

详细步骤:

1)以用户、WIFI 分组,在分组窗口内对数据按时间正序排序;2)依次遍历分组窗口内相邻两条记录,若两条记录之间的时间差超过 30 分钟,或者两条记录的行为状态(扫描态、连接态)发生变更,则以该临界点划分行为区间。直到遍历所有记录;

3)最终输出结果:用户、WIFI、行为状态(扫描态、连接态)、行为开始时间、行为结束时间;


-- SQL - 25select     user_id,     wifi,    max(status) as status,    min(time) as start_time,     max(time) as end_timefrom (    select *,        max(if(lag_status is null or lag_time is null or status <> lag_status or datediff(time, lag_time, 'ss') > 60 * 30, rn, null))             over (partition by user_id, wifi order by time) as group_idx    from (        select *,            row_number() over (partition by user_id, wifi order by time) as rn,            lag(time, 1) over (partition by user_id, wifi order by time) as lag_time,            lag(status, 1) over (partition by user_id, wifi order by time) as lag_status        from user_wifi_log    ) t1) t2group by user_id, wifi, group_idx;

user_id

wifi

status

start_time

end_time

101

cmcc-Starbucks

scan

2024-01-01 10:01:00

2024-01-01 10:03:00

101

cmcc-Starbucks

conn

2024-01-01 10:04:00

2024-01-01 10:06:00

101

cmcc-Starbucks

conn

2024-01-01 11:01:00

2024-01-01 11:03:00


该案例中的连续性判别条件可以推广到更多场景,例如基于日期差值、时间差值、枚举类型、距离差值等作为连续性判别条件的数据场景。


结语


通过灵活的、散发性的数据处理思维,就可以用基础的语法,解决复杂的数据场景 是本篇文章贯穿全文的思想。文中针对数列生成、区间变换、排列组合、连续判别等常见的场景,给出了相对通用的解决方案,并结合实例进行了实际运用的讲解。

本篇文章尝试独辟蹊径,强调灵活的数据处理思维,希望能让读者觉得眼前一亮,更希望真的能给读者产生帮助。同时毕竟个人能力有限,思路不一定是最优的,甚至可能出现错误,欢迎提出意见或建议。

相关实践学习
简单用户画像分析
本场景主要介绍基于海量日志数据进行简单用户画像分析为背景,如何通过使用DataWorks完成数据采集 、加工数据、配置数据质量监控和数据可视化展现等任务。
SaaS 模式云数据仓库必修课
本课程由阿里云开发者社区和阿里云大数据团队共同出品,是SaaS模式云原生数据仓库领导者MaxCompute核心课程。本课程由阿里云资深产品和技术专家们从概念到方法,从场景到实践,体系化的将阿里巴巴飞天大数据平台10多年的经过验证的方法与实践深入浅出的讲给开发者们。帮助大数据开发者快速了解并掌握SaaS模式的云原生的数据仓库,助力开发者学习了解先进的技术栈,并能在实际业务中敏捷的进行大数据分析,赋能企业业务。 通过本课程可以了解SaaS模式云原生数据仓库领导者MaxCompute核心功能及典型适用场景,可应用MaxCompute实现数仓搭建,快速进行大数据分析。适合大数据工程师、大数据分析师 大量数据需要处理、存储和管理,需要搭建数据仓库?学它! 没有足够人员和经验来运维大数据平台,不想自建IDC买机器,需要免运维的大数据平台?会SQL就等于会大数据?学它! 想知道大数据用得对不对,想用更少的钱得到持续演进的数仓能力?获得极致弹性的计算资源和更好的性能,以及持续保护数据安全的生产环境?学它! 想要获得灵活的分析能力,快速洞察数据规律特征?想要兼得数据湖的灵活性与数据仓库的成长性?学它! 出品人:阿里云大数据产品及研发团队专家 产品 MaxCompute 官网 https://www.aliyun.com/product/odps&nbsp;
相关文章
|
6月前
|
SQL 分布式计算 数据处理
如何充分发挥 SQL 能力?
如何充分发挥 SQL 能力,是本篇文章的主题。本文尝试独辟蹊径,强调通过灵活的、发散性的数据处理思维,就可以用最基础的语法,解决复杂的数据场景。
158038 59
|
4月前
|
SQL Java 数据库
慢SQL的治理经验
在当今的数字化时代,数据库已经成为企业不可或缺的核心组件。然而,随着数据量的不断增加和查询的复杂性提高,慢查询成为了数据库性能的瓶颈之一。慢SQL不仅会影响系统的响应速度,还可能导致数据丢失或损坏,给企业带来巨大的损失。因此,慢SQL的治理成为了数据库管理的重要任务之一。本文将分享一些慢SQL的治理经验,包括如何识别、分析和优化慢查询。通过了解慢查询的原因和解决方法,我们可以提高数据库的性能和稳定性,为企业的业务发展提供更好的支持。
185 2
|
9月前
|
SQL 机器学习/深度学习 存储
高级SQL查询技巧——利用SQL改善和增强你的数据
高级SQL查询技巧——利用SQL改善和增强你的数据
443 0
|
SQL 人工智能 Serverless
使用AI优化慢SQL,开发秒变DBA
慢 SQL 经常会让应用程序响应变慢,轻者影响用户体验,严重的时候可能会导致服务不可用。如果,每次遇到慢 SQL 都求助于 DBA,一方面效率很低,另一方面也会很没面子。所以,我们一起来看看如何使用AI能力给出超越一般DBA的 SQL 优化建议。NineData( www.ninedata.cloud )面向每个开发人员提供了免费的 SQL 开发功能,同时也提供了免费的 AI SQL 优化功能。
587 0
使用AI优化慢SQL,开发秒变DBA
|
SQL 存储 Oracle
使用 NineData 高效编写 SQL
作为与数据库交互如此重要的SQL,如何准确、高效的编写正确的SQL语句得以运行,很大程度上将与研发效率直接挂钩。NineData在SQL窗口中实现了多个功能,帮助大家更便捷的书写SQL与数据库进行交互。
574 0
使用 NineData 高效编写 SQL
|
SQL 存储 数据采集
数据分析中的SQL如何解决业务问题
在工作中,每个数据分析师都离不开做数据分析报告,而一份可落地的报告更是要求灵活地应用工具及理论知识。接下来,我们从工具应用的角度,看看如何用SQL做一份完整的数据分析报告。
|
SQL 存储 并行计算
大数据计算,如何优化SQL?
很多大数据计算都是用SQL实现的,跑得慢时就要去优化SQL,但常常碰到让人干瞪眼的情况。
834 0
大数据计算,如何优化SQL?
|
SQL 存储 分布式计算
三端一体计算方案:Unify SQL Engine
本文将介绍数仓建设过程中面对三种计算模式,较低的研发效率、不可控的数据质量,以及臃肿数据接口服务的困境的解决方案。
309 0
三端一体计算方案:Unify SQL Engine
|
SQL 分布式计算 资源调度
SQL 开发任务超 50% !滴滴实时计算的演进与优化
Apache Flink 是一个分布式大数据处理引擎,可对有限数据流和无限数据流进行有状态计算。可部署在各种集群环境,对各种大小的数据规模进行快速计算。滴滴基于 Apache Flink 做了大量的优化,也增加了更多的功能,比如扩展 DDL、内置消息格式解析、扩展 UDX 等,使得 Flink 能够在滴滴的业务场景中发挥更大的作用。
Uma
|
SQL 新零售 关系型数据库
最佳实践 | 教你用一条SQL搞定跨数据库查询难题
数据库拆分后,数据分布到不同的数据库实例,可达到降低数据量,增加实例数的扩容目的。然而前途是美好的,道路是曲折的。一旦涉及拆分,就逃不开“原本在同一数据库里的查询,要变成跨两个数据库实例”的查询问题。
Uma
3727 0

热门文章

最新文章