云计算百科
云计算领域专业知识百科平台

Power BI 2022 + 新增窗口函数解析

一、2022 + 新增窗口函数核心特点与优势(vs 传统函数)

函数核心特点传统替代函数核心优势性能 / 易用性对比
OFFSET 动态相对偏移,基于当前行取偏移 N 行数据,支持分区 / 排序 / 空值控制 DATEADD/PREVIOUSMONTH(时间类)、FILTER+TOPN(通用) 1. 脱离时间维度限制,适配任意维度偏移;2. 原生支持分区(PARTITIONBY),无需嵌套ALLEXCEPT;3. 语法简洁,减少嵌套层级 性能提升 30%-50%(大数据量);语法量减少 60%
INDEX 静态绝对索引,基于固定位置(第 N 行 / 最后一行)取数,参数与OFFSET完全兼容 FILTER+TOPN+COUNTROWS 1. 直接定位固定行,无需计算偏移;2. 分区索引(如按年取首行)无需额外逻辑;3. 支持-1直接取最后一行,简化极值查询 性能提升 50%+;无需手动计算行位置,不易出错
WINDOW 自定义窗口范围(相对 / 绝对),支持多行列聚合,覆盖滚动 / 累计 / 帕累托分析 FILTER+SUMX+EARLIER(累计)、TOPN+SUMX(滚动) 1. 原生支持窗口范围定义,无需手动筛选;2. 支持ABS/REL双位置类型,适配所有窗口场景;3. 分区窗口计算更简洁 性能提升 40%-70%(数据量>10 万行时更明显);代码量减少 70%
RANK 简化版排名函数,原生支持分区 / 多字段排序 / 并列处理 RANKX 1. 无需手动指定排名数据集,语法更简洁;2. 原生支持PARTITIONBY分区排名;3. 多字段排名无需嵌套CONCATENATEX 性能持平,但语法量减少 50%,可读性提升
ROWNUMBER 连续行号生成,支持分区 / 排序,无跳过行号 COUNTROWS+FILTER+EARLIER 1. 原生支持分区行号(每个分区从 1 开始);2. 无需手动累加,避免上下文错误;3. 支持多列排序生成行号 性能提升 60%+;彻底解决传统行号的上下文冲突问题

二、基础数据(2024-2025 年,季度划分精准)

1. 日历表(Dim Calendar)

 DAX 生成:

Dim Calendar =
ADDCOLUMNS(
CALENDAR(
DATE( 2024 , 1 , 1 ) , // 开始日期
DATE( 2025 , 12 , 31 ) // 结束日期
),
"年度" , YEAR( [Date] ) ,
"月份" , MONTH( [Date] ) ,
"月份序号" , MONTH( [Date] ) ,
"季度" , "Q" & QUARTER( [Date] ) ,
"年度季度" , YEAR( [Date] ) & "Q" & QUARTER( [Date] ) ,
"月份名称 CN" ,
SWITCH(
MONTH( [Date] ),
1, "一月",
2, "二月",
3, "三月",
4, "四月",
5, "五月",
6, "六月",
7, "七月",
8, "八月",
9, "九月",
10, "十月",
11, "十一月",
12, "十二月",
"未知月份"
)
)

2. 销售表(Fact Sales)

修正后精准数据(按自然月 / 季度划分,手工计算可验证):

日期产品名称销售额成本指标一指标二是否达标(1 = 达标 / 0 = 未达标)年度季度年度季度
2024-01-01 产品 A 15000 7500 80 90 1 2024 Q1 2024Q1
2024-02-01 产品 A 16000 8000 85 88 1 2024 Q1 2024Q1
2024-03-01 产品 A 17000 8500 85 85 0 2024 Q1 2024Q1
2024-04-01 产品 A 18000 9000 90 92 1 2024 Q2 2024Q2
2024-05-01 产品 A 19000 9500 90 95 1 2024 Q2 2024Q2
2024-06-01 产品 A 20000 10000 90 95 1 2024 Q2 2024Q2
2024-07-01 产品 A 21000 10500 92 96 1 2024 Q3 2024Q3
2024-08-01 产品 A 22000 11000 92 97 1 2024 Q3 2024Q3
2024-09-01 产品 A 23000 11500 92 98 1 2024 Q3 2024Q3
2024-10-01 产品 A 24000 12000 95 99 1 2024 Q4 2024Q4
2024-11-01 产品 A 25000 12500 95 99 0 2024 Q4 2024Q4
2024-12-01 产品 A 26000 13000 95 99 1 2024 Q4 2024Q4
2025-01-01 产品 A 27000 13500 98 100 1 2025 Q1 2025Q1
2025-02-01 产品 A 28000 14000 98 100 0 2025 Q1 2025Q1
2024-01-01 产品 B 8000 4000 70 80 1 2024 Q1 2024Q1
2024-02-01 产品 B 9000 4500 75 82 0 2024 Q1 2024Q1
2024-03-01 产品 B 8500 4200 75 81 0 2024 Q1 2024Q1
2024-04-01 产品 B 9500 4800 80 85 1 2024 Q2 2024Q2
2024-05-01 产品 B 10000 5000 82 86 1 2024 Q2 2024Q2
2024-06-01 产品 B 10500 5200 82 87 1 2024 Q2 2024Q2

关键手工验证值(季度汇总)

年度季度产品 A 销售额产品 B 销售额合计销售额
2024Q1 15000+16000+17000=48000 8000+9000+8500=25500 73500
2024Q2 18000+19000+20000=57000 9500+10000+10500=30000 87000
2024Q3 21000+22000+23000=66000 66000
2024Q4 24000+25000+26000=75000 75000
2025Q1 27000+28000=55000(仅 1-2 月) 55000

三、窗口函数详细解析(修正版案例 + 精准验证)

1.1 OFFSET(动态查询、求连续值)

OFFSET完整语法:

OFFSET(
delta,// 偏移行数:正值=当前行后,负值=当前行前,支持DAX表达式
<relation> or <axis>,// 可选:表表达式/视觉轴,默认ALLSELECTED(orderBy/partitionBy列)
orderBy, // 可选:排序方式,省略则按relation列默认排序
blanks,// 可选:空值处理(DEFAULT/FIRST/LAST)
partitionBy, // 可选:分区依据,按指定列分区后各自偏移
matchBy,// 可选:定义行匹配规则(唯一标识行)
reset// 可选:视觉计算重置(仅视觉轴场景)
)

1.1.1 不使用 orderBy

案例 1:获取上个季度销售额(无分区)

— 基础度量值(修正版)
销售额 = SUM('Fact Sales'[销售额])

— OFFSET取上季度销售额(无分区)
OFFSET-上季度销售额 =
CALCULATE(
[销售额],
OFFSET(
-1,// 向前偏移1行
ALLSELECTED('Dim Calendar'[年度季度])// 偏移的数据集
)
)

精准结果验证:

年度季度销售额OFFSET – 上季度销售额
2024Q1 73500
2024Q2 87000 73500
2024Q3 66000 87000
2024Q4 75000 66000
2025Q1 55000 75000

案例 2:按年度分区取上季度销售额

OFFSET-年度内上季度销售额 =
CALCULATE(
[销售额],
OFFSET(
-1,
ALLSELECTED('Dim Calendar'[年度季度],'Dim Calendar'[年度]),,, // 空出orderBy/blanks参数
PARTITIONBY('Dim Calendar'[年度]) // 按年度分区
)
)

精准结果验证(年度内偏移,跨年度重置):

年度年度季度销售额OFFSET – 年度内上季度销售额
2024 2024Q1 73500
2024 2024Q2 87000 73500
2024 2024Q3 66000 87000
2024 2024Q4 75000 66000
2025 2025Q1 55000
1.1.2 使用 orderBy

案例:按月份序号取上月销售额

OFFSET-上月销售额 =
CALCULATE(
[销售额] ,
OFFSET(
-1, // 向前偏移1行(上月)
ALLSELECTED( 'Dim Calendar'[月份名称 CN] , 'Dim Calendar'[月份序号] ), // 数据集
ORDERBY( 'Dim Calendar'[月份序号] , ASC ) // 按月份序号升序排序
)
)

精准结果验证(2024 年 1-4 月):

月份名称 CN月份序号销售额OFFSET – 上月销售额
一月 1 23000
二月 2 25000 23000
三月 3 25500 25000
四月 4 27500 25500
1.1.3 统计连续值的最大出现次数(待补充)

案例:统计产品 A 连续达标的最大月份数

1.2 INDEX(静态查询)

INDEX完整语法:

INDEX(
position,// 检索位置:1=第一行,-1=最后一行,越界返回空表
<relation> or <axis>,// 可选:表表达式/视觉轴,同OFFSET
orderBy, // 可选:排序依据,同OFFSET
blanks,// 可选:空值处理,同OFFSET
partitionBy, // 可选:分区依据,同OFFSET
matchBy,// 可选:行匹配规则,同OFFSET
reset// 可选:视觉计算重置,同OFFSET
)

案例 1:获取全表第一季度销售额(无分区)

INDEX-第一季度销售额 =
CALCULATE(
[销售额],
INDEX(1,ALLSELECTED('Dim Calendar'[年度季度])) // 取第1行(2024Q1)
)

精准结果:无论筛选哪个季度,均返回73500(2024Q1 合计销售额)。

案例 2:按年度分区获取本年第一季度销售额

INDEX-年度内第一季度销售额 =
CALCULATE(
[销售额],
INDEX(
1,
ALLSELECTED('Dim Calendar'[年度季度],'Dim Calendar'[年度]),,,
PARTITIONBY('Dim Calendar'[年度]) // 按年度分区
)
)

精准结果验证:

年度年度季度INDEX – 年度内第一季度销售额
2024 2024Q1 73500
2024 2024Q2 73500
2025 2025Q1 55000
案例 3:取产品销售额最后一行(最新月份)

INDEX-产品最新销售额 =
VAR AggregatedSingleTable =
SUMMARIZE(
// 基础表:事实表(已与日期表建立关联)
ALLSELECTED('Fact Sales'),
// 分组字段1:产品名称(来源于事实表)
'Fact Sales'[产品名称],
// 分组字段2:日期(通过表关系关联日期表,等价保留日期表的外部筛选条件)
'Dim Calendar'[Date],
// 计算每个(产品+日期)组合对应的销售额
"ProductDateSales", CALCULATE(SUM('Fact Sales'[销售额])) // 直接计算避免重复筛选,提升效率
)
RETURN
CALCULATE(
[销售额],
INDEX(
-1, // 选取每组中日期最新的一行
AggregatedSingleTable, // 数据范围为SUMMARIZE生成的单张聚合表
ORDERBY('Dim Calendar'[Date], ASC),
PARTITIONBY('Fact Sales'[产品名称])
)
)

精准结果:

  • 产品 A:28000(2025-02)
  • 产品 B:10500(2024-06)

1.3 WINDOW(滚动求和、累计求和、帕累托分析)

WINDOW完整语法:

WINDOW(
from[, from_type],// 窗口开始位置+类型:ABS=绝对位置,REL=相对位置(默认)
to[, to_type],// 窗口结束位置+类型:同from_type
<relation> or <axis>,// 可选:表表达式/视觉轴,同OFFSET
<orderBy>,// 可选:排序依据,同OFFSET
<blanks>,// 可选:空值处理,同OFFSET
<partitionBy>,// 可选:分区依据,同OFFSET
<matchBy>,// 可选:行匹配规则,同OFFSET
<reset>// 可选:视觉计算重置,同OFFSET
)

1.3.1 滚动求和与累计求和

案例 1:滚动求和(近 2 个季度销售额求和)

WINDOW-近2季度滚动销售额 =
CALCULATE(
[销售额],
WINDOW(
-1,REL, // 开始:当前行前1行(REL=相对位置)
0,REL, // 结束:当前行
ALLSELECTED('Dim Calendar'[年度季度]),
ORDERBY('Dim Calendar'[年度季度], ASC)
)
)

精准结果验证:

年度季度销售额WINDOW – 近 2 季度滚动销售额
2024Q1 73500 73500
2024Q2 87000 160500(73500+87000)
2024Q3 66000 153000(87000+66000)
2024Q4 75000 141000(66000+75000)
2025Q1 55000 130000(75000+55000)

案例 2:累计求和(年初至今销售额)

WINDOW-年初至今销售额 =
CALCULATE(
[销售额],
WINDOW(
1,ABS, // 开始:分区第1行(ABS=绝对位置)
0,REL, // 结束:当前行
ALLSELECTED('Dim Calendar'[年度季度], 'Dim Calendar'[年度]),
ORDERBY('Dim Calendar'[年度季度], ASC),,,
PARTITIONBY('Dim Calendar'[年度]) // 按年度分区累计
)
)

精准结果验证:

年度年度季度销售额WINDOW – 年初至今销售额
2024 2024Q1 73500 73500
2024 2024Q2 87000 160500(73500+87000)
2024 2024Q3 66000 226500(160500+66000)
2024 2024Q4 75000 301500(226500+75000)
2025 2025Q1 55000 55000
1.3.2 帕累托分析(二八定律)

案例:产品销售额帕累托分析(80% 销售额对应产品占比)

— 步骤1:单个产品总销售额
产品销售额 = CALCULATE([销售额], ALLSELECTED('Dim Calendar'[Date]))

— 步骤2:所有产品总销售额
总销售额 = CALCULATE([销售额], ALL('Fact Sales'[产品名称]))

— 步骤3:WINDOW计算累计销售额(按销售额降序)
累计销售额 =
CALCULATE(
[销售额],
WINDOW(
1,ABS, // 开始:第1行(销售额最高)
0,REL, // 结束:当前行
ALLSELECTED('Fact Sales'[产品名称]),
ORDERBY([产品销售额], DESC) // 按销售额降序排序
)
)

— 步骤4:累计销售额占比
累计销售额占比 = DIVIDE([累计销售额], [总销售额], 0)

— 步骤5:贡献80%销售额的产品占比
80%销售额产品占比 =
VAR Pareto80 =
FILTER(
ALLSELECTED('Fact Sales'[产品名称]),
[累计销售额占比] <= 0.8
)
RETURN
DIVIDE(COUNTROWS(Pareto80), COUNTROWS(ALL('Fact Sales'[产品名称])), 0)

精准结果验证:

  • 产品 A 总销售额:15000+16000+17000+18000+19000+20000+21000+22000+23000+24000+25000+26000+27000+28000 = 301000
  • 产品 B 总销售额:8000+9000+8500+9500+10000+10500 = 55500
  • 总销售额:301000+55500 = 356500
  • 产品 A 占比:301000/356500 ≈ 84.43%(已超 80%)
  • 最终80%销售额产品占比返回50%(仅产品 A 就覆盖 80%+ 销售额)。

1.4 RANK(多字段排名 / 分区排名)

RANK完整语法:

RANK (
[<ties>],// 可选:并列处理(SKIP=跳跃排名,DENSE=连续排名),默认SKIP
[<relation> or <axis>],// 可选:表表达式/视觉轴,同OFFSET
[<orderBy>],// 可选:排序依据,支持多字段
[<blanks>],// 可选:空值处理,同OFFSET
[<partitionBy>],// 可选:分区依据,同OFFSET
[<matchBy>],// 可选:行匹配规则,同OFFSET
[<reset>]// 可选:视觉计算重置,同OFFSET
)

案例 1:多字段排名(指标一降序→指标二降序)

— 基础度量值
指标一合计 = SUM('Fact Sales'[指标一])
指标二合计 = SUM('Fact Sales'[指标二])

— 多字段排名
多字段排名 =
RANK(
SKIP, // 并列跳跃排名
ALLSELECTED('Fact Sales'[产品名称]),
ORDERBY([指标一合计], DESC, [指标二合计], DESC) // 先指标一,后指标二
)

精准结果验证:

产品名称指标一合计指标二合计多字段排名
产品 A 80+85+85+90+90+90+92+92+92+95+95+95+98+98 = 1267 90+88+85+92+95+95+96+97+98+99+99+99+100+100 = 1323 1
产品 B 70+75+75+80+82+82 = 464 80+82+81+85+86+87 = 501 2
案例 2:分区排名(按月份分区,产品销售额排名)

月度产品销售额排名 =
RANK(
DENSE, // 并列连续排名
ALLSELECTED('Dim Calendar'[月份], 'Fact Sales'[产品名称]),
ORDERBY([销售额], DESC),,,
PARTITIONBY('Dim Calendar'[月份]) // 按月份分区
)

精准结果验证(2024 年 1 月):

月份产品名称销售额月度产品销售额排名
1 产品 A 15000 1
1 产品 B 8000 2

1.5 ROWNUMBER(分区行号 / 连续行号)

ROWNUMBER完整语法:

ROWNUMBER (
[<relation> or <axis>],// 可选:表表达式/视觉轴,同OFFSET
[<orderBy>],// 可选:排序依据,同OFFSET
[<blanks>],// 可选:空值处理,同OFFSET
[<partitionBy>],// 可选:分区依据,同OFFSET
[<matchBy>],// 可选:行匹配规则,同OFFSET
[<reset>]// 可选:视觉计算重置,同OFFSET
)

案例 1:全表连续行号(按销售额降序)

产品连续行号 =
ROWNUMBER(
ALLSELECTED('Fact Sales'[产品名称]),
ORDERBY([产品销售额], DESC)
)

精准结果:

  • 产品 A 行号:1
  • 产品 B 行号:2
案例 2:分区行号(按年度分区,季度行号)

年度内季度行号 =
ROWNUMBER(
ALLSELECTED('Dim Calendar'[年度], 'Dim Calendar'[季度]),
ORDERBY('Dim Calendar'[季度], ASC),,,
PARTITIONBY('Dim Calendar'[年度])
)

精准结果验证:

年度季度年度内季度行号
2024 Q1 1
2024 Q2 2
2024 Q3 3
2024 Q4 4
2025 Q1 1
案例 3:筛选前 N 行(取年度内前 1 个季度数据)

年度内前1季度数据 =
FILTER(
ALLSELECTED('Dim Calendar'[年度季度], 'Dim Calendar'[年度]),
[年度内季度行号] <= 1
)

精准结果:仅返回 2024Q1、2025Q1 的数据。

四、核心总结

  • 函数使用关键:
    • 分区计算必须将分区字段加入relation参数(如年度分区需包含年度列);
    • 时间类偏移 / 索引优先按月份序号/年度季度排序,避免中文月份排序错误;
    • 大数据量场景下,WINDOW替代传统FILTER+SUMX可显著提升性能(40%-70%)。
  • 赞(0)
    未经允许不得转载:网硕互联帮助中心 » Power BI 2022 + 新增窗口函数解析
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!