跳至正文

DAX Guide-7-DAX表函数全新分类与理解

DAX(Data Analysis Expressions)是一种用于计算和分析数据的语言,常用于Power BI和Excel中。其中,表函数(table functions)是难点。喜乐君在学习过程中,借助于如下的分类,简化了理解。

  • 从数据表到数据表的两种类型
  • 在数据表基础上增加字段列(计算列或度量值),从而构建新的数据表
  • 多表合并

一、从底表到逻辑表的两种基本形式

数据表的查询和分析,都是从table到table的过程,这被称之为SQL的“闭合性原则”,确保了SQL可以不断地嵌套。

通常,也可以视为从“物理表”到“逻辑表”的过程,当然,也可以是“逻辑表”进一步到“逻辑表”。前后可以用“底表”base table和logical table来代替。

第一类 数据表的筛选,即从table筛选出来特定的明细行

  • Filter函数 ,既可以是一个条件,也可以是多个条件。

多个优先级相同条件的FILTER,相当于多次筛选的交集(intersection)计算,也就是集合运算。但如果多个条件有优先级次序,那么也会出现不取交集的情况。比如

FILTER(sales, ALL( [product]), [product] = “red”)

……后续补充。

第二类 数据表的投影,即从table保留指定的数据列,其中有可以根据是否去重分为两类:

  • 数据表多个字段列的投影函数:
    • ALL,返回多个字段列构成的数据表
    • ALL的特殊形式,是投影整个数据表,此时可以写 ALL (table_name)
  • 数据表多个字段列投影并去重
    • SUMMARIZE函数,多个字段列分组
    • VALUES,单一字段列的去重投影,可以返回空值
    • DISTINCT,单一字段列的去重投影,不含空值
    • FILTERS,返回单一字段列构成的数据表,可以视为ALL的单列形式,和ALL一样,优先级较高

二、在逻辑表基础上,增加其他字段

在DAX中,可以通过创建新的计算列或者使用计算表(calculated table)来在一个数据表基础上追加字段,从而构成一个新表。其中,又可以分为增加计算列(行级别)和增加度量值(指定问题详细级别)两种类型。

  1. 在原有明细表中追加计算列,相当于扩展了已有物理表:计算列是在现有的数据表中创建一个新的列,并使用表达式定义该列的计算逻辑。示例如下:
sales[amt] = sales[quantity] * sales[Unit_price]

众所周知,计算列是需要占用内存空间的,它会预先计算,相当于Excel后面追加了一个新列,这个新列的优先级很好,因此可以在后续的问题分析中承担任意角色——既可以被聚合,也可以用作筛选,或者分组依据。

  1. 在聚合表基础上,增加度量值,相当于扩展了逻辑表:度量值是在现有的数据模型中创建一个新的逻辑字段,它可以进一步追加到各种逻辑表中,特别是问题对应的分组表。可以通过使用 SUMMARIZE 函数和其他 DAX 函数来创建逻辑表,并扩展。如下所示:
SUMMARIZECOLUMNS (
    Sales[ProductKey],
    Sales[CustomerKey],
    "total qty", sales[amt]
)

其中,Sales 是现有的数据表名称,Sales[ProductKey]和 Sales[CustomerKey] 作为问题的详细级别构建了一个分组表。sales[amt]是一个 DAX 表达式,用于定义度量值,并以total qty的字段名称追加到前面生成的分组表中。

通过在 SUMMARIZE 函数中指定要分组的列和计算表达式,可以创建一个新的逻辑表,该计算表包含了附加的度量值。

当然,SUMMARIZE类似的还有SUMMARIZEcolumn、addcolumn等函数,也是类似的逻辑。其中addcolumn用于在明细表中增加字段列,其他的基于字段分组构建字段列。起点略有不同。

当然,在上述过程中,有时候还会遇到从另一个数据表中引用字段的情况,类似于Excel的VLOOKUP函数,DAX中可以使用related完成。同理,还有很多数据表函数,用于多表之间的合并。

三、多表合并

在很多时候,单表不能解决问题,于是就有多表的合并。多表合并又有Union和Join两种基本形式。当然,Union和join,既可以在明细上完成,又可以在聚合表后完成。

在DAX中,可以将多个表合并生成新表的方法可以按照”Union”和”Join”两类进行分类,而先不考虑合并的table是physical table,还是logical table。

1. Union (合并)

  • UNION:将两个或多个表按行合并,生成一个包含所有行的新表。合并的表必须具有相同的列结构。 例如:
    Sales_East = UNION(Sales_2019, Sales_2020) 
    这将创建一个名为Sales_East的新表,其中包含Sales_2019Sales_2020两年份的销售数据。

2. Join (连接)

  • CROSSJOIN:将两个或多个表进行交叉连接。
    交叉连接会将一个表中的每一个行与另一个表中的每一个行进行组合,生成一个新的表。 例如:
    Sales_Combined = CROSSJOIN(Products, Regions) 
    这将创建一个名为Sales_Combined的新表,其中包含了Products表和Regions表中的所有可能组合,用于分析产品销售数据和地区相关信息。
  • NATURALINNERJOIN:在两个表之间执行内连接操作,根据共有列的值进行匹配。内连接操作会返回两个表中共有的行。 例如:
    Sales_Region = NATURALINNERJOIN(Sales, Regions) 
    这将创建一个名为Sales_Region的新表,其中包含了SalesRegions表中根据共有列(如地区代码)进行匹配的行,用于分析销售数据和地区信息的关联。
  • NATURALLEFTOUTERJOIN:在两个表之间执行左外连接操作,根据共有列的值进行匹配。左外连接操作会返回左表中的所有行以及与右表匹配的行。 例如:
    Employees_Department = NATURALLEFTOUTERJOIN(Employees, Departments) 

    这将创建一个名为Employees_Department的新表,其中包含了Employees表中的所有员工信息以及与Departments表根据共有列(如部门代码)匹配的部分部门信息。

  • NATURALRIGHTOUTERJOIN:在两个表之间执行右外连接操作,根据共有列的值进行匹配。右外连接操作会返回右表中的所有行以及与左表匹配的行。 例如:
    Departments_Employees = NATURALRIGHTOUTERJOIN(Departments, Employees) 
    这将创建一个名为Departments_Employees的新表,其中包含了Departments表中的所有部门信息以及与Employees表根据共有列(如部门代码)匹配的部分员工信息。

沿着这样的分类逻辑,DAX中的表函数(table functions)就能更好地理解了。

Sep 3, 2023 喜乐君 V0.1


了解 喜乐君 的更多信息

订阅后即可通过电子邮件收到最新文章。