跳至正文

SQL 向左,DAX 向右:数据库范式与分析范式的思维碰撞

XILEJUN
喜乐君 Tableau Visionary ✦ 5
📊 业务数据分析「专家」· 敏捷 BI 布道师
📚 《数据可视化分析》《业务可视化分析》多本书作者
🎓 中国地质大学(武汉)经管学院 MBA 校外导师
🤝 以 Tableau 会友,致力于构建业务分析通识框架

📚 本文配套课程 · SQL 系列

🎬 B 站课程:DAX「别裁新解」  —  https://www.bilibili.com/cheese/play/ss8780


喜乐君注:在学习 Tableau 的路上,我日渐兼修了PowerBI 和 DAX 知识,虽然不算娴熟,但基本了解了它们的技术逻辑。也写过几篇“Power 向左、Tableau 向右”主题的问题,颇为欢迎。

如今,我想对比一下 SQL 和 DAX 的差异。

引言:数据世界的两种“母语”

在浩瀚的数据世界里,SQL (Structured Query Language) 以其超过半个世纪的统治力,成为了无可争议的“世界语”。任何与数据打交道的人,都无法绕开它。然而,随着商业分析的复杂度与实时性要求日益提高,人们逐渐发现,这门“世界语”在某些场景下显得愈发“笨拙”和冗长。

正是在这样的背景下,一门全新的语言——DAX (Data Analysis Expressions) 应运而生。它并非SQL的替代品,而是一种从根本上为“分析”而生的新范式。它代表了一种与SQL截然不同的思考数据的方式。

概述:工具对比的本质——两种范式的对决

本文将沿用“向左,向右”的分析框架,深入剖析 SQL 所代表的“数据库范式”与 DAX 所代表的“分析范式”在哲学思想、设计逻辑和应用场景上的本质区别。在深入它们的分歧之前,我们有必要先看看这两位“巨人”共同站立的基石,再追溯其分道扬镳的历史根源,最后通过七个维度的直接对话,彻底理解它们的本质不同。

Venn diagram illustrating the relationship between SQL and DAX, with SQL represented on the left featuring a table icon, DAX on the right with a chart icon, and a shared green area in the center indicating their commonalities.

第一部分:求同存异 —— SQL 与 DAX 的共同基石

尽管我们强调其差异,但 SQL 与 DAX 并非全然对立。它们共享着作为现代数据语言的某些根本属性,这些共性是它们能够成为各自领域基石的原因。

1.1 数据交互的本质: 它们都是为“与数据对话”而生的领域专用语言(DSL),是人类与结构化数据存储之间沟通的桥梁,核心使命都是从数据中提取信息。

1.2 声明式的优雅: 两者都是声明式语言。使用者只需“声明”想要什么(What),而无需关心底层引擎**如何(How)**去实现。这使得它们在数据处理上更简洁、门槛更低,让使用者能更专注于业务逻辑本身。

1.3 大数据分析的能力: 两者都能处理海量数据。SQL 依托于强大的分布式数据库引擎(如 Spark SQL, Presto),DAX 则依赖于其背后高效的 VertiPaq 列式内存引擎。在各自的体系内,它们都具备处理亿级甚至更大规模数据的计算能力。

1.4 嵌入与集成的开放性: 两者都具备良好的生态集成性。SQL 可以被嵌入到几乎所有的编程语言和应用程序中;DAX 则作为微软分析平台的核心,能与 Power BI、Excel、SQL Server Analysis Services 等无缝集成。

一个图表展示了SQL和DAX在数据交互、数据分析能力、声明式优雅和生态集成性的对比。

第二部分:分道扬镳 —— 历史、使命与受众的差异

正是因为历史背景、核心使命和目标用户的不同,决定了 SQL 和 DAX 从诞生之初就走向了两条截然不同的道路。

2.1 历史渊源:生于“数据库时代” vs. 生于“分析时代”

  • SQL: 诞生于上世纪 70 年代 IBM 的 System R 项目。它的核心使命是解决当时新兴的关系型数据库的数据存储、管理和事务处理问题。它是“IT 工程化”时代的产物,追求的是数据的准确、一致和高效存取
  • DAX: 诞生于 2010 年前后,源于微软的 Power PivotSSAS Tabular Model。它的核心使命是解决复杂业务计算和报表敏捷性的问题,诞生于内存计算技术成熟、“业务敏捷化”需求爆发的时代。

2.2 核心使命:管理“数据资产” vs. 创造“业务洞察”

  • SQL: 其目标是成为数据库的“总管”,负责数据的增、删、改、查(CRUD),以及定义表结构(DDL)、控制访问权限(DCL)。其首要任务是确保数据资产的完整、安全与一致
  • DAX: 其目标是成为分析师的“大脑”,它只负责**“查”(Query)**,并将其能力发挥到极致。它的存在,就是为了将经过工程化处理的原始数据,转化为蕴含业务逻辑、驱动决策的深刻洞察

2.3 目标用户:数据工程师 vs. 数据分析师

  • SQL: 主要面向构建和维护数据基础设施的技术人员——数据工程师、ETL 开发者、后端工程师。他们使用 SQL 来构建稳健的数据流水线(Data Pipeline)。
  • DAX: 主要面向使用数据来回答业务问题的分析人员——数据分析师、BI 开发者、业务专家。他们使用 DAX 来构建蕴含业务逻辑的分析模型。

第三部分:范式对决 —— 七个维度的深度比较(文章核心)

这部分是文章的核心。我们将通过七个关键维度的直接对比,深入剖析两种范式的本质不同。

A comparison chart highlighting the differences between SQL and DAX across various dimensions, including language scope, dynamic interaction, key operations, abstraction layers, and understanding models.
维度SQL:数据库范式(向左)DAX:分析范式(向右)
3.1 认知模型自下而上的“数据建筑”: 必须从底层表结构和 JOIN 关系开始构建,要求使用者成为“数据建筑师”。自上而下的“业务翻译”: 从抽象的业务问题出发,假定模型正确,核心任务是将业务问题翻译成“分析表达式”,要求使用者成为“业务翻译官”。
3.2 语言结构语句式的“子句组合”: 一个完整的、结构化的语句 (Statement),由 SELECT, FROM, WHERE 等子句 (Clauses) 构成,语法依赖关系严格。函数式的“表达式嵌套”: 核心构建块是函数 (Function),整个逻辑是一个或多个函数的嵌套组合,最终形成一个表达式 (Expression),逻辑组织更灵活。
3.3 核心概念静态的“数据集合”: 操作对象是定义好的、静态的集合(表或视图)。一次查询,一次返回,结果固定。动态的“评估上下文”: 结果严重依赖于动态的行上下文 (Row Context) 和筛选上下文 (Filter Context)。DAX 是为了响应报表中的实时筛选变化而设计的。
3.4 抽象层次面向过程的封装: 通过视图(View)或存储过程(Stored Procedure)来封装复杂的查询逻辑,本质上是封装了一段“数据处理的过程”。面向业务的封装: 通过度量值(Measure)来封装一个“业务逻辑”。一个度量值代表一个业务概念,并能根据上下文(筛选器)正确地自我计算。
3.5 关键操作JOIN: 核心操作是连接数据表以生成新的数据集合。CALCULATE: 核心操作是上下文转换(Context Transition),即通过修改或创建筛选上下文,实现动态、非聚合数据的聚合计算。
3.6 动态性/交互性为“静态请求”而生: 一个 SQL 查询是对数据库的一次性“请求-响应”。它不理解、也不关心用户在前端界面的操作。为“动态交互”而活: 计算引擎与前端交互紧密耦合。用户在 Power BI 报表上的每一次点击,都触发 DAX 引擎在新的上下文下重新计算。
3.7 语言范围广博的“数据库总管”: 涵盖 DDL(定义)、DML(操作)、DCL(控制),是数据库的全能管家。专注的“分析手术刀”: 它只对应 SQL 中 DML 的 Query 部分,但将这一领域耕作到了极致,提供了 SQL 难以企及的时间智能函数和上下文操控能力。
个人资料照片

SQL 向左,DAX 向右:数据库范式与分析范式的思维碰撞

导言:数据交互的两种范式

在数据科学与商业智能领域,结构化查询语言(SQL)与数据分析表达式(DAX)是两座无法绕开的高峰。然而,它们并非简单的同类竞争者,而是代表了两种截然不同的数据交互世界观。SQL 是数据状态管理的语言,其核心关注点在于信息的持久化、结构化完整性与一致性。DAX 则是分析建模的语言,其设计初衷是为了实现动态的、上下文敏感的复杂计算。本文标题中的“向左”与“向右”正象征着这一根本性的分野:SQL 承载着构建数据基石的结构化、基础性工作(左),而 DAX 则释放了基于数据进行探索、创造与分析的灵活性(右)。

这两种语言的基因差异,是其诞生时代所面临核心问题的直接产物。SQL 的起源可追溯至 20 世纪 70 年代,旨在解决大型共享数据银行中数据存取的复杂性问题 。当时,数据库专家需要一种能从复杂的层级或网状数据库中解放出来的工具,以提高编程效率和数据独立性。埃德加·科德(Edgar F. Codd)的关系模型及其催生的 SQL,正是为数据库专家管理中央共享资源而设计的解决方案 。数十年后,微软的“双子座计划”(Project Gemini)则旨在解决一个截然不同的商业痛点:业务分析师对 IT 部门的高度依赖,以及由此带来的分析敏捷性缺失 。其解决方案 DAX,是一种为 Excel 用户量身定制的公式语言,它在内存模型之上运行,核心目标是赋予业务人员探索数据的能力。因此,SQL 的设计解决了程序员的效率问题,而 DAX 的设计则解决了分析师的敏捷性问题。这种根本性的目标差异,决定了它们后续在哲学、架构和语法上的巨大分野。  

为了在深入探讨前建立一个宏观框架,下表对两种范式的核心维度进行了高阶对比,它将作为贯穿全文的参照系。

维度SQLDAX
核心范式数据库 / 状态管理 (Database / State Management)分析 / 语义建模 (Analytical / Semantic Modeling)
主要抽象表 / 关系 (Table / Relation)数据模型 / 多维数据集 (Data Model / Cube)
语言性质声明式 / 基于集合 (Declarative / Set-based)函数式 / 基于公式 (Functional / Formula-based)
主要用户数据工程师 / 数据库管理员 (Data Engineer / DBA)商业智能分析师 / 开发人员 (BI Analyst / Developer)
核心操作数据检索与持久化操作上下文驱动的动态计算
引擎设计通用关系型数据库 / 分布式 SQL 引擎专用内存列式引擎 (VertiPaq)

核心之辩:状态 vs. 上下文

如果说引擎架构是 SQL 和 DAX 的“身体”,那么它们处理数据的核心逻辑——状态(State)与上下文(Context)——就是它们的“灵魂”。SQL 的世界观是绝对的、基于静态集合的;而 DAX 的世界观则是相对的、基于动态上下文的。理解这一根本差异,是跨越两种范式思维鸿沟的关键。

4.1 SQL 的世界观:操作静态集合

一个 SQL 查询的执行过程,本质上是对数据库在某个时间点上的静态快照进行的一系列集合运算。其逻辑流程清晰而确定:

在整个查询执行期间,被操作的数据集合是固定的。对于一个给定的数据库状态,无论何时执行相同的 SQL 查询,其返回的结果集都是完全相同、绝对不变的。这个结果集本身也是一个静态的、新的表。SQL 的思维模式是线性的、程序化的,它通过一系列明确的步骤,从一个已知的、静态的数据状态中,精确地提取出一个新的、同样静态的数据子集。

4.2 DAX 的世界观:评估上下文

与 SQL 的绝对主义截然不同,DAX 的计算是在一个动态的、多层次的“评估上下文”(Evaluation Context)中进行的。任何一个 DAX 表达式的值都不是孤立存在的,它的结果完全取决于其被评估时所处的环境。这个评估上下文是 DAX 最核心、也最难掌握的概念,它由两个主要部分组成:行上下文(Row Context)和筛选上下文(Filter Context)。

  • 行上下文 (Row Context): 行上下文的核心是“当前行”的概念 。它本身并不筛选数据,而是提供一个迭代的指针,逐一扫描表的每一行。当存在行上下文时,DAX 表达式就可以直接引用当前行中任何一列的值。行上下文主要在两种情况下被创建:
    1. 计算列 (Calculated Columns): 当你在一张表中创建一个计算列时,DAX 会自动为该表的每一行创建一个行上下文,并逐行计算该列的表达式 。  
    2. 迭代器函数 (Iterator Functions):SUMXAVERAGEXFILTERADDCOLUMNS 这一类以 X 结尾或接受表作为输入的函数,会显式地创建一个行上下文。它们会遍历其第一个参数(一个表表达式)的每一行,并在该行上下文中执行其第二个参数(一个表达式) 。  
  • 筛选上下文 (Filter Context): 筛选上下文是应用于整个数据模型的一组活动筛选器 。它就像一副“分析眼镜”,决定了在进行任何计算之前,哪些数据是“可见的”。筛选上下文的来源主要有两个:
    1. 报表交互: 用户在 Power BI 报表中进行的任何操作,如点击切片器、在图表中选择数据点、应用页面或视觉对象级别的筛选器,都会自动生成或修改筛选上下文 。  
    2. CALCULATE 函数: CALCULATE 函数是 DAX 中唯一一个能够通过代码直接创建和修改筛选上下文的函数 。  

4.3 CALCULATE:动态分析的引擎

如果说评估上下文是 DAX 的灵魂,那么 CALCULATE 函数就是驱动这个灵魂的心脏。它是 DAX 中功能最强大、也是最重要的函数。其基本语法是 CALCULATE(<expression>, <filter1>, <filter2>,...),其核心作用是在一个修改过的筛选上下文中评估指定的表达式 。  

CALCULATE 的魔力在于其“上下文转换”(Context Transition)的能力 。当 CALCULATE 函数在一个已经存在行上下文的环境中被调用时(例如,在计算列或迭代器函数内部),它会执行一个神奇的操作:将当前的行上下文“提升”为一个新的筛选上下文 。这个新生成的筛选上下文会过滤整个数据模型,使其只包含当前行所代表的数据。  

例如,在 Product 表中创建一个计算列 CALCULATE(SUM(Sales[Quantity]))

  1. 计算列为 Product 表的每一行创建了一个行上下文。
  2. 当计算到“产品A”这一行时,CALCULATE 被调用。
  3. CALCULATE 将“产品A”这一行的行上下文,转换为一个筛选上下文,这个筛选上下文的效果等同于 FILTER(ALL(Product), Product = "A")
  4. 这个新的筛选上下文会通过关系传递到 Sales 表,筛选出所有与“产品A”相关的销售记录。
  5. 最后,SUM(Sales[Quantity]) 在这个被筛选过的 Sales 表上进行计算,得到只属于“产品A”的销售总量。

这个“上下文转换”机制是 DAX 独有的,它在行级迭代和模型级筛选之间架起了一座桥梁,使得在逐行计算的过程中,可以引用和操作整个数据模型经过筛选后的聚合结果。这是 SQL 中没有直接对应物的强大概念。

4.4 实践体现:计算列 vs. 度量值

计算列和度量值(Measures)的区别,是理解行上下文与筛选上下文在实践中如何运作的最佳范例 。  

特性计算列 (Calculated Column)度量值 (Measure)
计算时间数据刷新时计算,一次性完成。查询时计算,每次报表交互都会重新计算。
存储方式结果作为新的一列物理存储在模型中,消耗内存和磁盘空间。公式存储在模型中,结果不存储,计算时消耗 CPU。
主要上下文行上下文 (Row Context)。逐行计算,不感知报表筛选。筛选上下文 (Filter Context)。结果随报表筛选动态变化。
典型用途静态的、行级别的分类或属性。例如,根据价格将产品分为“高/中/低”档,或在切片器中使用。动态的、聚合性的业务指标。例如,“总销售额”、“利润率”,其值会根据用户选择的年份、地区等变化。

一个计算列 [Price] * [Quantity] 是在行上下文中工作的,它在每一行独立计算,结果是静态的,存储下来。而一个度量值 SUMX(Sales, Sales[Price] * Sales[Quantity]) 则是在筛选上下文中工作的,它的结果是动态的,取决于用户在报表中的交互。

最终,我们可以得出这样一个结论:SQL 查询的结果是绝对的,它反映了数据库在某个时刻的真实状态。而 DAX 度量值的结果是相对的,它是一个公式,其值取决于观察它的“参考系”——即评估上下文。CALCULATE 赋予了分析师操纵这个参考系的能力,从而实现了 SQL 难以企及的动态分析深度和灵活性。这正是从数据库范式到分析范式的核心思维跃迁。

SQL 向左,DAX 向右:范式的综合

在深入剖析了 SQL 与 DAX 的起源、架构和核心理念之后,我们不应将它们视为相互竞争、非此即彼的技术,而应理解为在现代数据工作流中相辅相成、各司其职的两种范式。它们之间的“碰撞”并非一场零和博弈,而是在现代数据栈中形成的一种高效分工与协作。

5.1 现代数据栈:一种共生关系

现代数据生态系统清晰地划分了数据处理的不同阶段,而 SQL 和 DAX 正好完美地契合了其中的关键环节,并分别对应着数据团队中的核心角色:数据工程师(Data Engineer)和数据分析师/商业智能开发者(Data Analyst / BI Developer)。  

  • SQL(向左):数据工程师的基石 SQL 是数据管道的“左侧”,是构建一切数据分析应用的基础。数据工程师是这个领域的专家,他们使用 SQL 来执行一系列关键的、结构性的任务 :
    • 数据集成与ETL/ELT: 从各种源系统(如 OLTP 数据库、API、日志文件)中提取原始数据,使用 SQL 进行清洗、转换、标准化,并加载到数据仓库或数据湖中 。  
    • 数据建模与仓库维护: 设计和构建数据仓库的模式(如星型模型、雪花模型),创建事实表和维度表,确保数据的结构化、一致性和高质量。
    • 性能优化与扩展: 编写高效的 SQL 查询,优化数据处理流程,确保数据基础设施能够稳定、可扩展地运行,为下游分析提供可靠的数据服务。 在这个阶段,SQL 的数据库范式——强调结构、持久化和状态管理——是至关重要的。数据工程师的目标是创建一个稳定、可信、高性能的“单一事实来源”(Single Source of Truth)。
  • DAX(向右):分析师的利器 DAX 则是数据价值链的“右侧”,是分析和洞察的舞台。数据分析师和 BI 开发者是这个领域的主角,他们接收由数据工程师准备好的高质量数据,并使用 DAX 来构建富有洞见的分析应用 :
    • 语义建模: 在 Power BI 或 Analysis Services 中,分析师使用 DAX 创建度量值和计算列,将原始的数据表转化为一个包含丰富业务逻辑的语义模型。这个模型是业务语言和底层数据之间的桥梁。
    • 动态报表与仪表板: DAX 的核心优势在于创建交互式报表。分析师利用其上下文驱动的计算能力,构建能够响应用户筛选和钻取的动态视觉对象,回答复杂的业务问题。
    • 高级分析: 使用 DAX 的时间智能函数、迭代函数和上下文操作能力,执行同比/环比分析、客户分群、预测建模等高级分析任务。 在这个阶段,DAX 的分析范式——强调上下文、动态计算和业务逻辑——发挥着核心作用。分析师的目标不是管理数据状态,而是在一个灵活的、交互式的环境中探索数据、发现模式并传达洞见。

5.2 两种思维模式的交响

掌握 SQL 和 DAX 不仅仅是学习两种语法,更是培养两种截然不同的思维模式。

  • SQL 思维:基于集合的构建者思维 SQL 思考者以数据表和集合为中心。他们考虑的是如何通过连接(JOIN)、过滤(WHERE)和聚合(GROUP BY)等操作,从一个或多个静态的表中构建出一个新的、满足特定条件的静态结果集。他们的问题是:“满足这些条件的数据是什么?” 这种思维是结构化的、自下而上的,专注于数据的转换和准备。
  • DAX 思维:基于模型的探索者思维 DAX 思考者以整个数据模型和评估上下文为中心。他们不再将表视为孤立的实体,而是看作一个相互关联的、由关系连接起来的语义网络。他们考虑的是一个度量值(如 “)在不同的筛选上下文(Filter Context)下应该如何动态地计算。他们的问题是:“在用户当前的视图下,这个值应该如何计算?” 这种思维是概念性的、自上而下的,专注于业务逻辑的表达和动态分析的实现。

现代数据栈的成功,正是源于对这两种范式和思维模式的深刻理解与制度化。它通过明确的角色分工(数据工程师 vs. 数据分析师)和技术栈分离(数据仓库 vs. BI 工具),为 SQL 和 DAX 的协同工作创造了理想的环境。数据工程师使用 SQL “向左”,为分析构建坚实的地基;数据分析师使用 DAX “向右”,在地基之上建造洞察的高楼。这种看似“碰撞”的范式差异,最终在实践中谱写出了一曲高效协作的数据价值交响乐。

附录:DAX 基础文献的比较分析

A.1 引言:两种思想流派

DAX 语言的底层机制是确定且唯一的,但通往精通之路的教学方法与认知框架却可以有不同的流派。在 DAX 学习社区中,两部著作分别代表了两种极具价值但视角不同的思想体系。通过对它们的比较分析,我们可以更深刻地理解掌握 DAX 所需的知识二元性:既要懂其然,也要懂其所以然。

A.2 经典范式:《DAX 权威指南》by Russo and Ferrari

由 Marco Russo 和 Alberto Ferrari 合著的《The Definitive Guide to DAX》被全球 DAX 社区公认为“圣经” 。这本书的教学方法是严谨的、自下而上的,它从 DAX 引擎的内部工作原理出发,来解释语言的每一个行为。  

其核心贡献在于对 DAX 引擎三大基石的权威阐释:

  1. 引擎架构: 书中详细剖析了公式引擎(FE)和存储引擎(SE)的分工协作机制,以及 VertiPaq 引擎的列式存储、压缩和内存计算原理 。这为读者理解 DAX 的性能表现和优化策略提供了坚实的物理基础。  
  2. 评估上下文: 该书对行上下文和筛选上下文给出了最精确、最技术化的定义,并用大量示例阐明了它们的区别、交互以及各自的创建时机 。它教会读者像 DAX 引擎一样去“思考”上下文。  
  3. CALCULATE 与上下文转换: 书中将 CALCULATE 函数置于核心地位,并深入讲解了上下文转换这一关键机制,揭示了 DAX 如何在行级迭代中执行模型级的筛选聚合 。  

《DAX 权威指南》的アプローチ是工程师式的。它通过揭示“它如何工作”(how it works)的底层逻辑,赋予读者解决复杂问题和进行深度性能优化的能力。对于任何希望成为 DAX 专家的从业者而言,这本书是不可或缺的技术基石。

A.3 另辟蹊径:《DAX 别裁新解》by 喜乐君

喜乐君的著作(根据用户查询所提供的框架推断)则代表了另一种教学思想。它似乎更侧重于从分析师的业务视角出发,构建一个自上而下的、更符合人类认知习惯的 conceptual framework,来帮助读者理解和应用 DAX。

其独特的贡献可能体现在以下几个方面:

  1. “问题分析的两个阶段”: 这个框架很可能将一个完整的分析任务划分为“数据准备阶段”和“问题分析阶段” 。前者可能对应着需要在数据加载时就固化的、行级别的计算和分类,这在概念上与行上下文计算列的用途高度契合。后者则对应着在报表交互中进行的动态聚合与比较,这正是筛选上下文度量值的核心领域 。这个框架将抽象的技术概念映射到了分析师熟悉的实际工作流程中。  
  2. 上下文的重新诠释: 传统术语如“筛选上下文”对于初学者可能存在一定的误导性。该书可能提出了一些更直观的类比或命名,以帮助读者更好地理解其“筛选”和“限定计算范围”的本质,从而降低认知负荷 。  
  3. SUMMARIZE vs. SUMMARIZECOLUMNS 的深层辨析: 通过对这两个看似功能相似的函数进行深入区分,该书可能揭示了 DAX 在构建汇总表时的层次性 。SUMMARIZE 可能被诠释为更底层的、在行上下文中操作的物理表生成工具,而 SUMMARIZECOLUMNS 则被视为更现代、更直接在筛选上下文中工作的分析查询工具。这种辨析不仅是语法层面的,更是思维模式层面的。  

《DAX 别裁新解》的アプローチ是分析师式的。它通过提供一个“如何思考它”(how to think about it)的认知框架,帮助读者建立正确的 DAX 思维模式,使写出的代码不仅技术上正确,而且逻辑上优雅,与业务问题高度契合。

《SQL 向左,DAX 向右:数据库范式与分析范式的思维碰撞》有1个想法

  1. Pingback: “SQL 向左,DAX 向右” 深度对比-Tableau喜乐君-敏捷BI布道师

评论已关闭。