如何充分发挥 SQL 能力?

如何充分发挥 SQL 能力,是本篇文章的主题。本文尝试独辟蹊径,强调通过灵活的、发散性的数据处理思维,就可以用最基础的语法,解决复杂的数据场景。

一、前言

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.1 常见数列

2.1.1 一个简单的递增数列

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

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

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

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

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

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

1)生成一个长度合适的数组,数组中的元素不需要具有实际含义;

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

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

2.1.2 等差数列

SQL 实现:

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

2.1.3 等比数列

SQL 实现:

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

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

-- SQL - 4
select sequence(1, 3, 1);

-- result
[1, 2, 3]

2.2 应用场景举例

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

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

场景描述

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

-- SQL - 5
with 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 。

GROUPING__ID bits
0 { ..., 0, 0, 0 }
1 { ..., 0, 0, 1 }
2 { ..., 0, 1, 0 }
3 { ..., 0, 1, 1 }
... ...
2n2n ...

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值