前途科技前途科技
  • 洞察
  • 服务
  • 关于
  • AI 资讯
    • 快讯
    • 产品
    • 技术
    • 商业
    • 政策
    • 初创
  • 洞察
  • 资源中心
    • 深度研究
      • AI 前沿
      • 案例研究
      • AI 知识库
    • 行业报告
      • 白皮书
      • 行业报告
      • 研究报告
      • 技术分享
      • 专题报告
    • 精选案例
      • 金融行业
      • 医疗行业
      • 教育行业
      • 零售行业
      • 制造行业
  • 服务
  • 关于
联系我们

揭秘DAX:筛选器如何驱动时间智能函数的幕后逻辑

教程2025年10月2日· 5 分钟阅读4 阅读

分析将从一个简单的表格开始: 图 1 – 用于分析的简单表格(作者供图) 矩阵可视化图表中的每一行都展示了每个 […]

分析将从一个简单的表格开始:

图 1 – 示例起始表格

图 1 – 用于分析的简单表格(作者供图)

矩阵可视化图表中的每一行都展示了每个月的在线销售总额。

到目前为止,一切看起来都非常直观。

直观的解释是:我们看到的是按月份筛选后的在线销售总额。

但这并非事情的全貌。

接下来,我们审视一下数据模型:

图 2 – 包含日期表和事实表的数据模型部分

图 2 – 包含日期表和事实表的数据模型部分(作者供图)

仔细观察,可以发现日期表(Date table)与事实表(fact table)之间是基于日期列(date columns)建立关系的。

与月份列(month column)之间并没有直接的关系。

如果沿着这个思路,上述的解释就不完全准确了。

更完整的解释应该是:每一行显示的是通过日期表筛选后的在线销售总额。日期表的行按月份进行分组。因此,每一行展示的是该月份所有日期的总销售额。

当理解了这一细节时,我们就离全面掌握 DAX 的工作原理,特别是时间智能函数的运作机制更近了一步。

现在,让分析更进一步。

YTD 与基础查询

现在,添加一个年度至今(YTD)度量值,观察其表现:

图 3 – YTD 度量值及其结果显示在与之前相同的表格中

图 3 – YTD 度量值及其结果显示在与之前相同的表格中(作者供图)

这个度量值本身并不复杂,其结果也易于理解。

接下来,深入探究 DATESYTD() 函数的具体功能。

dax.guide 网站对该函数的解释是:“返回一个在筛选上下文中,从年初到最后一个可见日期的日期集。”

这究竟意味着什么?

为了探究这个问题,我们首先编写一个 DAX 查询,以获取 2024 年 6 月的所有日期列表,正如上述可视化图表中所展示的那样:

DEFINE
    VAR YearFilter = TREATAS({ 2024 }, 'Date'[Year])
    VAR MonthFilter = TREATAS({ 6 }, 'Date'[Month])

EVALUATE
SUMMARIZECOLUMNS('Date'[Date]
,YearFilter
,MonthFilter
)

查询结果是 6 月份的 30 天日期列表:

图 4 – 获取 2024 年 6 月所有日期的基础查询

图 4 – 获取 2024 年 6 月所有日期的基础查询(作者供图)

这就是应用于上述矩阵图表中 2024 年 6 月那一行数据的筛选器。

那么,将 DATESYTD() 函数应用于这个结果会发生什么?

以下是相应的查询:

DEFINE
    VAR YearFilter = TREATAS({ 2024 }, 'Date'[Year])
    VAR MonthFilter = TREATAS({ 6 }, 'Date'[Month])
VAR BasisDates = CALCULATETABLE(
                        SUMMARIZECOLUMNS('Date'[Date]
                                    ,YearFilter
                                    ,MonthFilter
                                    )
                                )

VAR YTDDates = DATESYTD(TREATAS(BasisDates, 'Date'[Date])
                                )

EVALUATE
YTDDates

以及其结果:

图 5 – 从 1 月 1 日到 2024 年 6 月最后一天,包含所有日期的列表

图 5 – 从 1 月 1 日到 2024 年 6 月最后一天,包含所有日期的列表(作者供图)

这是一个包含 182 行数据的列表,其中包括从年初到 2024 年 6 月最后一天的所有日期。

这正是 YTD(年度至今)的定义。

当我们观察以下度量值时:

Online Sales (YTD) =
VAR YTDDates = DATESYTD('Date'[Date])

RETURN
CALCULATE([Sum Online Sales]
,YTDDates
)

就会发现变量 YTDDates “仅仅”是一个日期列表,作为筛选器应用于 CALCULATE() 函数。

这正是所有时间智能函数的核心关键。

回溯一年 — 示例

如果将另一个函数应用于此结果,例如 SAMEPERIODLASTYEAR(),又会发生什么?

为了回答这个问题,使用以下 DAX 查询:

DEFINE
    VAR YearFilter = TREATAS({ 2024 }, 'Date'[Year])
    VAR MonthFilter = TREATAS({ 6 }, 'Date'[Month])
VAR BasisDates = CALCULATETABLE(
                        SUMMARIZECOLUMNS('Date'[Date]
                                    ,YearFilter
                                    ,MonthFilter
                                    )
                                )

VAR YTDDates = DATESYTD(TREATAS(BasisDates, 'Date'[Date])
                                )

VAR YTDDatesPY = SAMEPERIODLASTYEAR(YTDDates)

EVALUATE
YTDDatesPY

为了提高代码的可读性,文章故意将 SAMEPERIODLASTYEAR() 函数的调用与 DATESYTD() 函数分开。实际上,也可以将 DATESYTD() 嵌套在 SAMEPERIODLASTYEAR() 中。

这一次,结果是 181 行数据,因为 2024 年是闰年。

并且日期都向后推移了一年:

图 6 – 应用 SAMEPERIODLASTYEAR() 后的查询结果

图 6 – 应用 SAMEPERIODLASTYEAR() 后的查询结果(作者供图)

所以,再次强调,当将时间智能函数应用于度量值时,该函数(例如 DATESYTD())会返回一个日期列表。

请注意:当应用此筛选器时,日期表上任何现有筛选器都将被清除。

自定义逻辑

现在,将这些知识应用于自定义时间智能逻辑的构建。

首先,稍微改变一下年份和月份的筛选器:

DEFINE
    VAR YearMonthFilter = TREATAS({ 202406  }, 'Date'[MonthKey])

EVALUATE
SUMMARIZECOLUMNS('Date'[Date]
, YearMonthFilter
)

这个查询的结果与文章开头展示的结果相同。

这一次,筛选器是通过对 [MonthKey] 列设置一个数值来实现的。

如何才能回溯到上一年呢?

从数学角度思考,只需减去 100 即可实现:

202406 – 100 = 202306

让我们尝试一下:

图 7 – 从 [MonthKey] 列中减去 100 后的查询结果

图 7 – 从 [MonthKey] 列中减去 100 后的查询结果(作者供图)

这种方法也适用于其他数字格式。

例如,如果使用像 2425 这样的会计年度格式(表示 24/25 财年),

可以通过减去 101 来获取上一个会计年度:2425 – 101 = 2324。

另一个自定义时间智能逻辑的例子是计算滚动平均值,其中每天的平均值是基于过去 10 天的数据计算的:

图 8 – 计算前 10 天移动平均值的度量值代码和结果

图 8 – 计算前 10 天移动平均值的度量值代码和结果(作者供图)

由于变量 DateRange 的内容同样是一个日期列表,因此可以对其应用 SAMEPERIODLASTYEAR() 函数,从而获得所需的结果:

DEFINE
    VAR YearFilter = TREATAS({ 2024 }, 'Date'[Year])
    VAR MonthFilter = TREATAS({ 6 }, 'Date'[Month])
// 1. 获取当前筛选上下文的起始和结束日期
VAR MaxDate = CALCULATE(MAX( 'Date'[Date] )
                        ,YearFilter
                        ,MonthFilter
                        )

VAR MinDate =
    CALCULATE(
        DATEADD( 'Date'[Date], - 10, DAY )
        ,'Date'[Date] = MaxDate
        )

// 2. 生成移动平均所需的日期范围(四个月)
VAR  DateRange =
 CALCULATETABLE(
    DATESBETWEEN( 'Date'[Date]
        ,MinDate
        ,MaxDate
    )
)

EVALUATE
SAMEPERIODLASTYEAR( DateRange )

以下是其结果:

图 9 – 上一年移动平均值的结果

图 9 – 上一年移动平均值的结果(作者供图)

这个逻辑返回 11 行数据,因为它包含了当月的最后一天。根据所需结果,可能需要调整计算日期列表(应用于度量值的筛选器)中起始日期和结束日期的方式。

这无疑是对前述内容的重复展示,但它旨在说明相同的思路可以应用于各种不同的场景。

一旦理解了这一点,处理时间智能函数以及其他接受值表作为输入的函数时,将变得更加轻松自如,得心应手。

结论

虽然文中使用了 DAX Studio 来执行这些查询,但您同样可以在 Power BI Desktop 内置的 DAX 查询工具中使用它们。

文章特意通过这些查询来强调,在 DAX 中,我们始终在与表打交道,即便有时可能没有明确意识到这一点。

但这却是理解 DAX 工作原理过程中一个至关重要的细节。

尽管随着 Power BI 中新的基于日历的时间智能功能出现,此处展示的一些 DAX 代码可能显得有些过时,但本文阐述的原理依然有效。DATESYTD() 或 SAMEPERIODLASTYEAR() 等函数仍然存在,并以相同的方式工作。目前而言,这方面不会有任何改变,因为本文描述的概念依然适用。

参考文献

与之前的文章一样,本文使用了 Contoso 示例数据集。您可以从 Microsoft 此处免费下载 ContosoRetailDW 数据集。

想了解 AI 如何助力您的企业?

免费获取企业 AI 成熟度诊断报告,发现转型机会

//

24小时热榜

阿联酋联手Colossal打造基因“诺亚方舟”
TOP1

阿联酋联手Colossal打造基因“诺亚方舟”

欧盟发布AI法案高风险系统关键指南
TOP2

欧盟发布AI法案高风险系统关键指南

3

OpenAI 从 Anthropic 挖角安全专家,年薪超 55 万美元

9小时前
OpenAI 从 Anthropic 挖角安全专家,年薪超 55 万美元
4

Claude 登顶 App Store,ChatGPT 遭抵制风波

13小时前
Claude 登顶 App Store,ChatGPT 遭抵制风波
5

伊朗袭击波及 AWS,阿联酋数据中心被迫关闭

13小时前
伊朗袭击波及 AWS,阿联酋数据中心被迫关闭
6

Linux基金会成立OCUDU基金会,加速开源5G/6G网络发展

12小时前
Linux基金会成立OCUDU基金会,加速开源5G/6G网络发展
7

数据中心断电暴露美国电网脆弱性

13小时前
数据中心断电暴露美国电网脆弱性
8

谷歌 Nano Banana 2 凌晨突袭!生图速度飙升,价格直接腰斩,Pro 功能竟然也免费了?

23小时前
谷歌 Nano Banana 2 凌晨突袭!生图速度飙升,价格直接腰斩,Pro 功能竟然也免费了?
热门标签
大模型AgentRAG微调私有化部署Prompt EngineeringChatGPTClaudeDeepSeek智能客服知识管理内容生成代码辅助数据分析金融零售制造医疗教育AI 战略数字化转型ROI 分析OpenAIAnthropicGoogle

关注公众号

前途科技微信公众号

扫码关注,获取最新 AI 资讯

免费获取 AI 落地指南

3 步完成企业诊断,获取专属转型建议

已有 200+ 企业完成诊断

前途科技前途科技
服务关于快讯技术商业报告
前途科技微信公众号

微信公众号

扫码关注

Copyright © 2026 AccessPath.com, 前途国际科技咨询(北京)有限公司,版权所有。|京ICP备17045010号-1|京公网安备 11010502033860号|隐私政策|服务条款