窗口函数是一种在指定分区内对数据进行排名或偏移取值的函数,它在不改变查询行数的前提下为每行数据附加计算值。窗口函数在数据库中完成计算,可结合过滤器面板实现组内TopN等分析场景。本文为您介绍窗口函数的语法、使用方法与典型应用场景。
使用限制
窗口函数仅支持以下数据源,且数据源版本需满足最低版本要求。
数据源 | 是否支持 | 最低版本 |
MySQL | 支持 | 8.0(5.7及以下不支持) |
AnalyticDB MySQL | 支持 | 3.0(仅支持 XIHE 引擎) |
PostgreSQL | 支持 | 9.4 |
ClickHouse | 支持 | 21.1 |
MaxCompute | 支持 | 全版本 |
Oracle | 支持 | 11g |
Hive | 支持 | 2.1.0 |
SQL Server | 支持 | 2012 |
此外,窗口函数还有以下使用限制:
数据建模:关系模型(多逻辑表数据集)不支持窗口函数。若需使用,请调整为物理层建模。
图表:明细表、趋势分析表、多维分析表不支持窗口函数。
函数嵌套:窗口函数不支持与LOD函数嵌套使用,也不支持与窗口函数嵌套使用。
分区字段:窗口函数中使用的分区字段必须拖入图表的维度中,否则数据库无法计算。
偏移行数:WINDOW_LAG和WINDOW_LEAD的偏移行数必须为正整数,且不超过999999999。
总计与小计:含窗口函数的字段不支持总计、小计,对应值显示为“-”。
背景介绍
在日常分析中,组内排名(如各区域利润排名前5的城市、各类目销售额TopN)、同比环比(如每个产品的上月销售额)、首末值对比(如各类目首日销售额)等需求十分常见。
此类需求也可以通过表计算实现,但表计算在内存中执行,受取数行数上限约束,数据量大时结果可能不完整。窗口函数则在数据库中直接完成排名、偏移等计算,再配合过滤器面板过滤,仅返回满足条件的数据行,可减少数据传输量并提升大数据量场景下的分析性能。
使用场景
窗口函数适用于以下典型分析场景:
场景 | 示例 | 对应函数 |
排名分析 | 各类目销售额排名、各区域业绩排行。 | WINDOW_ROW_NUMBER、WINDOW_RANK、WINDOW_DENSE_RANK |
同比环比 | 对比当月与上月、下月的销售额。 | WINDOW_LAG、WINDOW_LEAD |
首末值分析 | 各类目第一天或最后一天的销售额。 | WINDOW_FIRST_VALUE、WINDOW_LAST_VALUE |
组内TopN | 仅保留各分区内排名前N的数据行。 | 排名函数 + 过滤器面板 |
语法说明
窗口函数采用与LOD函数一致的分段式语法,以花括号({})包裹参数,各段之间以英文冒号分隔。窗口函数通过分区字段将数据划分为若干分区,并在每个分区内按排序表达式进行排名或偏移取值。各参数说明如下:
参数 | 说明 |
分区字段 | 指定分区(分组)的一个或多个维度,使用逗号分隔,可为空(表示全局排名)。 |
排序表达式 | 指定排序的字段或聚合表达式,支持ASC(升序)或DESC(降序),默认为ASC。支持多个字段,使用逗号分隔。 |
取值字段 | 指定要取值的表达式,必须为聚合字段或聚合表达式。仅偏移函数与首末值函数需要该参数。 |
偏移行数 | 指定向前或向后偏移的行数,必须为正整数。仅偏移函数需要该参数。 |
WINDOW_ROW_NUMBER
WINDOW_ROW_NUMBER用于对分区内的数据进行行号排名,不存在并列,每行分配唯一编号。
语法 | WINDOW_ROW_NUMBER{<分区字段> : <排序表达式>} |
定义 | 对分区内的数据进行“行号排名”,即:不存在并列,每行唯一编号。 |
输出 | 整数 |
示例 | WINDOW_ROW_NUMBER{[区域]: BI_SUM([订单金额]) DESC} 对各个区域的销售额进行降序的行号排名,如 (6, 9, 9, 14) -> (4, 2, 3, 1)。 |
WINDOW_RANK
WINDOW_RANK用于对分区内的数据进行跳跃排名,允许并列,并列后跳过后续编号。
语法 | WINDOW_RANK{<分区字段> : <排序表达式>} |
定义 | 对分区内的数据进行“跳跃排名”,即:允许并列,并列后跳过编号。 |
输出 | 整数 |
示例 | WINDOW_RANK{[区域]: BI_SUM([订单金额]) DESC} 对各个区域的销售额进行降序的跳跃排名,如 (6, 9, 9, 14) -> (4, 2, 2, 1)。 |
WINDOW_DENSE_RANK
WINDOW_DENSE_RANK用于对分区内的数据进行密集排名,允许并列,并列后不跳过编号。
语法 | WINDOW_DENSE_RANK{<分区字段> : <排序表达式>} |
定义 | 对分区内的数据进行“密集排名”,即:允许并列,并列后不跳过编号。 |
输出 | 整数 |
示例 | WINDOW_DENSE_RANK{[区域]: BI_SUM([订单金额]) DESC} 对各个区域的销售额进行降序的密集排名,如 (6, 9, 9, 14) -> (3, 2, 2, 1)。 |
WINDOW_LAG
WINDOW_LAG用于取分区内当前行之前第N行的值,若超出分区范围则返回NULL。
语法 | WINDOW_LAG{<分区字段> : <排序表达式> : <取值字段> : <偏移行数>} |
定义 | 取分区内,当前行之前第N行的值,若超出分区范围则返回NULL。 |
输出 | 数值 |
示例 | WINDOW_LAG{[产品]: [月份] ASC: BI_SUM([销售额]): 1} 以产品为分区,按月份升序排列,取前1行的销售额(即上一月销售额)。 |
WINDOW_LEAD
WINDOW_LEAD用于取分区内当前行之后第N行的值,若超出分区范围则返回NULL。
语法 | WINDOW_LEAD{<分区字段> : <排序表达式> : <取值字段> : <偏移行数>} |
定义 | 取分区内,当前行之后第N行的值,若超出分区范围则返回NULL。 |
输出 | 数值 |
示例 | WINDOW_LEAD{[产品]: [月份] ASC: BI_SUM([销售额]): 1} 以产品为分区,按月份升序排列,取后1行的销售额(即下一月销售额)。 |
WINDOW_FIRST_VALUE
WINDOW_FIRST_VALUE用于取分区内排序后第一行的值。
语法 | WINDOW_FIRST_VALUE{<分区字段> : <排序表达式> : <取值字段>} |
定义 | 取分区内排序后第一行的值。 |
输出 | 数值 |
示例 | WINDOW_FIRST_VALUE{[类目]: [日期] ASC: BI_SUM([销售额])} 以类目为分区,按日期升序排列,取每个分区第一行的销售额(即各类目第一天的销售额)。 |
WINDOW_LAST_VALUE
WINDOW_LAST_VALUE用于取分区内排序后最后一行的值。
语法 | WINDOW_LAST_VALUE{<分区字段> : <排序表达式> : <取值字段>} |
定义 | 取分区内排序后最后一行的值。 |
输出 | 数值 |
示例 | WINDOW_LAST_VALUE{[类目]: [日期] ASC: BI_SUM([销售额])} 以类目为分区,按日期升序排列,取每个分区最后一行的销售额(即各类目最后一天的销售额)。 |
操作步骤
在数据集编辑页面,单击新建计算字段。

填写字段名称(①),在字段表达式中输入窗口函数表达式(②),并配置字段类型等配置项(③)。
例如,字段名称填写“区域利润排行”,字段表达式填写:WINDOW_ROW_NUMBER{[区域]: BI_SUM([利润金额]) DESC}。

单击确定完成新建。
(可选)如需筛选组内TopN,将该字段拖入过滤器面板并设置过滤条件。
例如,设置为小于或等于5,即仅保留各分区内排名前5的数据行。

使用该字段创建仪表板图表,即可查看窗口函数的计算结果。
应用案例
各区域利润排名前5的城市
分析各区域利润金额最高的前5个城市时,使用窗口函数可一次计算所有区域的排名,再通过过滤器筛选。
新建计算字段“区域利润排名”,字段表达式填写:WINDOW_ROW_NUMBER{[区域]: BI_SUM([利润金额]) DESC}。

即以区域为分区,按利润金额合计降序排列,为每行分配唯一排名。
创建交叉表,将区域、城市拖入行区域,将利润金额和区域利润排名拖入列区域。
将区域利润排名拖入过滤器面板,设置过滤条件为小于或等于5。

单击更新,交叉表中仅展示各区域中利润排名前5的城市。

各产品类型销售额排行(允许并列)
分析各类目下产品的销售额排名且允许并列时,使用WINDOW_RANK或WINDOW_DENSE_RANK代替WINDOW_ROW_NUMBER。
新建计算字段“各产品类型销售额排行”,字段表达式填写:WINDOW_RANK{[产品类型]: BI_SUM([销售金额]) DESC}。

即以类目为分区,按销售额合计降序排列,允许并列且并列后跳号。
创建交叉表,将产品类型、产品名称拖入行区域,将销售金额和各产品类型销售额排行拖入列区域。
单击更新,订单金额相同的产品获得相同排名编号。

WINDOW_RANK:并列后跳号,如 1、2、2、4。
WINDOW_DENSE_RANK:并列后不跳号,如 1、2、2、3。
各城市的上月销售额(环比基础)
在展示各产品每月销售额的同时展示其上月销售额,可用于计算环比增长率。
新建计算字段“各城市上月销售额”,字段表达式填写:WINDOW_LAG{[城市]: [订单月份] ASC: BI_SUM([订单金额]): 1}。

即以城市为分区,按月份升序排列,取当前行前1行的销售额。
创建交叉表,将城市、订单月份拖入行区域,将订单金额和各城市上月销售额拖入列区域。
单击更新,各产品的首月无上月数据,显示为空,其余月份展示对应的上月销售额。

如需计算环比增长率,可再新建计算字段,表达式为:(BI_SUM([销售额]) - [上月销售额]) / [上月销售额]。
常见问题
窗口函数和表计算有什么区别?
表计算在内存中执行,数据库返回全量数据后再计算排名;窗口函数在数据库中执行,配合过滤器面板可在数据库侧完成组内TopN过滤,仅返回满足条件的数据行,大数据量场景下性能更优。
分区字段可以为空吗?
可以。分区字段为空时表示全局排名,即对整个结果集统一计算,如 WINDOW_ROW_NUMBER{: BI_SUM([销售额]) DESC}。
如何实现组内TopN?
分两步:先新建排名计算字段,如 WINDOW_ROW_NUMBER{[类目]: BI_SUM([销售额]) DESC};再将该字段拖入过滤器面板并设置过滤条件,如小于或等于5。
为什么MySQL数据源提示不支持窗口函数?
MySQL从8.0版本开始支持窗口函数。请检查数据源版本,若低于8.0,请升级数据源版本或更换数据源。
窗口函数可以和LOD函数一起使用吗?
支持在同一查询中分别使用LOD函数字段和窗口函数字段,两者各自独立计算。但不支持在窗口函数表达式内嵌套LOD表达式。




