当前位置:首页 > 问答 > 正文

树叶云带你简单聊聊OceanBase那些分析函数怎么用,入门不难理解

树叶云带你简单聊聊OceanBase那些分析函数怎么用,入门不难理解 主要参考自OceanBase官方文档、社区技术博客及部分用户实践分享)

好,咱们开始聊,今天不说复杂的,就用大白话讲讲OceanBase里的分析函数,你可能听过窗口函数,其实就是它,叫法不同而已,这东西听起来高级,但理解了核心思想后,会发现它其实很贴心,能帮我们解决很多SQL里以前觉得麻烦的问题。

先弄明白:分析函数是干啥的?

想象一下你有一张学生成绩表,里面有学生姓名、班级、成绩,现在你想做两件事:

  1. 查每个学生的成绩。
  2. 顺便看看每个学生在他自己班级里的成绩排名。

第一件事很简单,一个SELECT * FROM 成绩表就搞定了,但第二件事就有点棘手了,传统方法可能需要先按班级分组算出排名,然后再和原表连接,写起来啰嗦,执行起来也可能慢。

这时候分析函数就派上用场了。它的核心想法是:在查询出每一行数据的同时,还能看到与这一行“相关联”的一组数据(这个组就叫“窗口”)的计算结果。 关键点是,它不会像GROUP BY那样把多行合并成一行,而是原表的每一行都还在,只是额外多了一列计算出来的信息。

就像给你班级花名册,在每个人名字后面,不仅印上他的分数,还直接印上他在班里的排名,这样一眼就看全了。

分析函数长啥样?一个万能公式

树叶云带你简单聊聊OceanBase那些分析函数怎么用,入门不难理解

它的基本语法结构可以看成这样: 分析函数名(参数) OVER ([PARTITION BY 分组字段] [ORDER BY 排序字段] [窗口框架])

别怕,我们一点点拆开看:

  1. 分析函数名(参数):这就是你要干什么,比如ROW_NUMBER()(算行号)、RANK()(算排名)、SUM(成绩)(求和)、AVG(成绩)(求平均)等等。
  2. OVER():这是关键标志,告诉数据库“我后面要开始定义窗口了”。
  3. PARTITION BY:相当于分组,比如PARTITION BY 班级,就是说我这个计算(比如排名)是在每个班级内部进行的,一班排一班的,二班排二班的,互不干扰,这部分是可选的,如果省略,就是把整个表当成一个大的分组。
  4. ORDER BY:在窗口内部,按哪个字段排序,这对排名类、累计求和类函数至关重要,比如ORDER BY 成绩 DESC,就是按成绩从高到低排。
  5. 窗口框架:这个稍微进阶点,但也很直观,它定义了这个“窗口”具体有多大,比如是“从分组的开头到当前行”(用于算累计值),还是“当前行前后几行”(用于算移动平均),初学可以先放一放,大部分场景用不到。

举几个接地气的例子

假设我们有张销售表sales,字段有:销售员salesman、销售月份month、销售额amount

例1:给每个销售员的业绩按月排名

树叶云带你简单聊聊OceanBase那些分析函数怎么用,入门不难理解

SELECT
  salesman,
  month,
  amount,
  ROW_NUMBER() OVER (PARTITION BY salesman ORDER BY amount DESC) as rank_in_salesman
FROM sales;
  • PARTITION BY salesman:按每个销售员单独划窗口。
  • ORDER BY amount DESC:在每个销售员的窗口里,按销售额从高到低排。
  • ROW_NUMBER():给排好序的行分配一个连续的序号(1,2,3...)。 结果就是,你会看到每个销售员的每条销售记录,后面都跟着一个数字,表示他本人当月业绩在自己所有业绩中的排名。

例2:计算每个销售员每个月的累计销售额

SELECT
  salesman,
  month,
  amount,
  SUM(amount) OVER (PARTITION BY salesman ORDER BY month) as cumulative_amount
FROM sales;
  • PARTITION BY salesman:还是按销售员分。
  • ORDER BY month:这次按月份排序,这很重要!
  • SUM(amount):求和,但因为是分析函数,并且有ORDER BY,默认的窗口框架就是“从分组的开始到当前行”,所以它算的是累计和。 结果就是,一月份显示一月业绩,二月份显示一月+二月业绩,三月份显示一月至三月业绩,以此类推,非常方便。

例3:查看每个销售员当月业绩占他个人总业绩的比例

SELECT
  salesman,
  month,
  amount,
  amount / SUM(amount) OVER (PARTITION BY salesman) as ratio
FROM sales;
  • 注意这个OVER (PARTITION BY salesman)里面没有ORDER BY
  • 因为没有ORDER BY,窗口框架就是整个分组,所以SUM(amount)算的就是每个销售员所有月份的总销售额。
  • 然后用当月金额除以这个总额,就得到了占比。

初学容易迷糊的点

  1. 和GROUP BY的区别:这是最大的坎,再强调一遍,GROUP BY会把行合并,你SELECT的字段要么是分组的字段,要么是聚合函数结果,而分析函数是“原样输出所有行”,只是每行多了一个计算列,它们经常可以配合使用。
  2. ORDER BY的影响:在分析函数里,ORDER BY不仅影响排序,还会影响像SUM, AVG这类聚合函数的计算范围(即窗口框架),让它变成累计计算,如果你不想累计,只想在每个分组内整体计算,就不要写ORDER BY
  3. 几个排名函数的区别
    • ROW_NUMBER():永远产生连续的序号(1,2,3,4...),即使成绩相同。
    • RANK():相同值排名相同,但会跳号,比如两个并列第一,下一个就是第三名。
    • DENSE_RANK():相同值排名相同,但不会跳号,比如两个并列第一,下一个就是第二名。

总结一下

OceanBase的分析函数(窗口函数)是个超级好用的工具,你只要抓住“针对每一行,看它所在窗口的统计信息”这个核心,多写几个例子试试手感,很快就能上手,它让那些需要子查询、表连接才能完成的复杂排序、分组计算变得非常简单直接。

入门真的不难,你需要的只是打破对它的陌生感,下次写SQL时,当你发现“我想在查详细数据的同时,还想知道它在这个组里的位置或比例”,那就该想到分析函数了,放心去用,它能极大提升你处理数据的效率和能力。