09.2 EVALUATE
DAX是一门编程语言也是一门查询语言
初识EVALUATE
DAX查询是返回表的DAX表达式,与EVALUATE语句联用。完整的DAX查询语法示例如下:[DEFINE{MEASURE []= }]EVALUATE
[ORDER BY{[{ASC | DESC}]}[, …][START AT{|}[, …]]]初始的 DEFINE MEASURE 定义了用于本地查询的度量值(也就是说,它们存在于当前查询的生命周期中)。当调试公式时,它会非常有用,因为你可以定义一个局部变量,测试它,一旦它可以按照预期的行为运行,就把它放到模型中。稍后你将看到关于这种语法的更多示例。查询语法主要由可选参数组成,最简单的查询是从现有表中检索所有列和行:EVALUATE Product产品表的查询结果## ORDER BY 字句
如果要控制结果的排序规则,可以使用ORDER BY字句EVALUATE ProductORDER BY Product[Color],Product[Brand]ASC,Product[Class]DESC在模型中定义的 “按列排序” 属性在 DAX 查询中没有效果。即使你可以通过按列排序属性查询单个列来查看排序数据, 你也不必依赖于此行为, 就像你不能依赖 SQL 查询中的聚集索引一样。生成动态 DAX 查询的客户端应读取模型元数据中的 “按列排序” 属性, 然后按条件生成相应的排序。在DAX和SQL中,必须始终使用通过显式ORDER BY排序的数据作为结果。## ASC和DESC 关键词
ASC和DESC关键字是可选的;如果未声明, 则默认使用ASC。你可以在下图中看到上一查询的结果, 其中数据按颜色、品牌和类别进行排序。产品表查询结果,品牌和颜色按升序排列,类别按降序排列## START AT 关键词
START AT条件也是可选的,只能与ORDER BY子句结合使用。你可以在ORDER BY语句中为每个列指定起始值。在无状态应用程序中,START AT条件对于分页非常有用,这些应用程序只从查询中获取有限数量的行,然后在用户请求下一页数据时发送另一个查询。例如,查看以下查询:EVALUATE ProductORDER BY Product[Color],Product[Brand]ASC,Product[Class]DESCSTART AT”Yellow”,”Tailspin Toys”查询返回如图所示的表格,其中只包含从”Yellow”、 “Tailspin Toys”开始的行对已排序的产品表的查询结果从Yellow、Tailspin Toys 的组合开始请注意,从哪里起始这个概念取决于ORDER BY子句中指定的顺序方向。如果Product[Brand]被指定为DESC,如下例所示,结果中将不包括Wide World Importers,而其他品牌,如Southridge Video和Northwind Trader,会在Tailspin Toys后显示。EVALUATE ProductORDER BY Product[Color],Product[Brand]DESC,Product[Class]DESCSTART AT”Yellow”,”Tailspin Toys”产品表按品牌降序,查询结果将从Yellow ,Tailspin Toys brand的组合开始若要筛选行并更改 DAX 查询返回的列, 必须在EVALUATE关键字后使用一些特定的表函数处理表表达式。# 深入了解 EVALUATE
EVALUATE是用于计算和物化表的DAX声明,考虑到 DEFINE MEASURE 对调试公式很有用,接下来会详细解释,因为通常你会将表函数用作度量值中使用的标量表达式的筛选器参数,但是在SQL Server Management Studio和DAX Studio等环境中测试它们要容易得多,在这些环境中,你可以编写返回表的查询。## 介绍 DEFINE MEASURE
[DEFINE{MEASURE []= }]EVALUATE 你可以使用EVALUATE语句定义一个或多个度量值,如下面的示例所示:DEFINEMEASURE Sales[Quantity]=SUM(Sales[Quantity])MEASURE Sales[Total Cost]=SUMX(Sales,Sales[Quantity] Sales[Unit Cost])EVALUATEADDCOLUMNS(VALUES(Product[Brand]),”Quantity”,[Quantity],”Cost”,[Total Cost])使用此语句,你必须将度量值与表名相关联,如果使用表中已存在的名称,在行上下文不存在时,将在EVALUATE中重写原表达式。例如,前面的示例将用同名度量值覆盖表的Quantity列。你在结果的每一行中看到的值是为每个品牌聚合所有行的Quantity列的总和。
实际上,除了这种情况之外,不建议在度量值前加表名
通常,在查询中重写已有名称不是一个好主意。尽管如此,当你希望将数据模型中定义的度量值替换为查询使用的临时定义时(通常是出于调试或优化的原因),这是非常有用的。例如,假设你有一个查询,如下所示,其中度量值Discounted Sales不能得到正确结果:EVALUATEADDCOLUMNS(VALUES(Product[Brand]),”Discounted Sales”,[Discounted Sales])你可以创建具有相同名称的本地度量值,并对其进行修改和测试,直到计值正确为止,然后才在数据模型中复制更正后的度量值:DEFINEMEASURE Sales[Discounted Sales]=SUMX(Sales,Sales[Quantity](Sales[Unit Price]- Sales[Unit Discount]))EVALUATEADDCOLUMNS(VALUES(Product[Brand]),”Discounted Sales”,[Discounted Sales])在查询中重写数据模型的度量值不会影响数据模型的其他代码中对该度量值的现有引用。例如,考虑以下两个数据模型中的度量值:[Total Sales]:=SUMX(Sales,Sales[Quantity]* Sales[Net Price])[Average Price]:=[Total Sales]/SUM(Sales[Quantity])如果在查询中重写了Total Sales,你将看到它不会影响Average Price的计算,如下面的示例所示:DEFINEMEASURE Sales[Total Sales]=0EVALUATEADDCOLUMNS(VALUES(Product[Brand]),”Total Sales”,[Total Sales],”Average Price”,[Average Price])Average Price在数据模型中计值,使用Total Sales的原生定义而不是在本地查询中的临时定义。## 在EVALUATE中使用VAR
你可以在EVALUATE语句中使用一种与标准语法略有不同的方式定义变量,通常使用的语法是:VAR = RETURNRETURN之后的表达式可以访问前面定义的变量。这种语法可以替换DAX中的任何标量或表表达式。但是,当你编写EVALUATE语句时,你也可以在DEFINE的部分定义变量,而不必在之后编写RETURN:DEFINEVAR ExpensiveProducts =FILTER(Product,Product[Unit Price]>3000)EVALUATECALCULATETABLE(Product,ExpensiveProducts)一个更完整的EVALUATE语法定义如下:[DEFINE[{MEASURE []= }][{VAR = }]]EVALUATE 在任何情况下,只有在EVALUATE后的表达式中使用该变量时,才会对该变量计值,并且变量的计算环境不依赖于在定义变量后发生的筛选上下文操作。换句话说,你也可以使用VAR/Return语法,如以下示例所示:EVALUATEVAR ExpensiveProducts =FILTER(Product,Product[Unit Price]>3000)RETURNCALCULATETABLE(Product,ExpensiveProducts)