变量(6)
1、 回顾变量的特点与作用
(1)变量的实际是缓存数据,它具有一次性计算、一个计算式里可重复引用,替代“当前行”(构建行筛选—条件筛选),可将函数表表达式、列表或列表结果、值列表、度量计算式等定义为变量以便公式引用,并可用于度量、计算列以及查询……;
(2)可以求同一列中的行比较之类的累计占比、排名、移动聚合类(如移动平均)计算,实现类似EARLIER() 的效果;
(3)变量在DAX里运用的通用公式:
VAR V_1 = 列表、列值或函数计算式01
VAR V_2 = 列表、列值或函数计算式02
……
VAR V_N = 列表、列值或函数计算式N
return
CALCULATE ( 计算列表,
FILTER ( ALL('被筛选表'), 含变量的筛选))
(3)其他。请自行回顾或参阅前面有关变量系列的内容。
2、 综合业务场景
由于实际的业务数据模型的不同,在度量、计算列、或者查询里设置变量的需求也会不同。以后有机会不断的聊到这个问题。这里,请原谅我的惰性,让我们结合简体化的一篇整理修改稿来简单讨论一下。同时,变量系列也将告一段落。
在进行之前,先引出问题。提一下我在另一篇《超市数据分析的思维模式(一)》:网页地址:https://mp.weixin.qq.com/s/w-Se54mPtk9wpYQ-LEwFDg 里提到的“利用量化思维解决抽象性业务问题”,其中所使用的“抽象物”是引用IBM前总裁郭士纳有一句名言:下属不会做你希望他做的事情,他们只会做你监督和检查的事情 ?在那篇文章里,我们讨论了比较抽象的这句话,是如何运用数据思维将它“量化”出来。
可是,这里我们所说的是DAX的变量!跟这句话似乎有些“牛头不对马嘴”?其实不然,因为变量也是“量化”的工具,能帮助你定义度量里的逻辑条件。我们简单的聊一下前面的绩效度量问题。
前面引用的一句话(抽象物),于销售管理来说,我们设想一个业务场景:例如想要通过一系列不同的业务绩效,以便将销售人员的工作集中在某些重要的方面(目的是驱动业务)。正如俗话所说:“只有度量它,才能完成它”。这种度量的东西就是量化。
当然,学过Power BI、Power Pivot以及PowerQurey的,知道这些是完成此类报告的优秀工具。这里,因为不是讨论Power BI的好处以及使用它们的一大堆原因……。简而言之,为了搞个简单实用点的业务绩效考核度量。或者说:理清如何度量。
以下参考了部分简体化内容。
3、案例简述
假如设置一个“年度团队”奖,该奖项基于许多不同的数据来源:包括销售业绩、执行效果、新产品发布效果、客户信息等 — 这是相当标准的销售数据模型。
考虑设置团队在每个领域都获得了一些基于绩效的分数,每个可用的分数点对应于每个业务驱动的重要性(或者设置加权值)。每个团队在总的业务下都以各自的区域表现得分(比如零售营业员对应其管辖的商品区域),然后将这些积分加起来获得总分,以得分大小求得获胜队或其他分组的队。
这是一个常见的绩效业务逻辑问题。关键是将它度量出来:
首先,我们为销售增长分配点数(分值)。
这里分享一个公式:为某种业务(领域)的销售增长分配评分值。其中分配的业务规则如下:
• 如果销售与去年相比有所下降,则团队不得分(零分);
• 与去年相比, 在0 - 1%之间,每增长0.1%,团队就会得100分;
• 与去年相比,完成任务超过1%之后,再每超过0.1%,团队就会得200分。
然后,设计决策(业务逻辑)
这时, 必须确定的第一件事是如何设置以及维护好这些业务规则。可能想到的3个选项:
(1)将业务逻辑直接定义到公式本身中;
(2)创建一个包含所有关键数值的参数表(例如:分配多少个分值的列,以要获得这些分值的上下触发分值的列等等);
(3)使用VAR变量语法编写公式(因为VAR变量更像是一个“常量”,从某种意义上说,也是一类参数值。因为变量具备与元列表没有关系、以及值列表的特点)。
你当然已经猜到了结论:使用选项3是最好的。要不然这篇文章就没有了“主人公”。
与使用VAR语法相比,选项2--加载参数表并提取值的工作相对来说要求较高。考虑到业务规则的使用仅限于这一个公式,我觉得VAR语法是最好的选择。
最后,写出DAX公式
这是我最后写的公式,但通常情况下,我认为写公式的过程比最终的公式更有趣,更有用。
Growth Points =
VAR Points = 100 --points
VAR DoubleBonusPointsLevel = 0.01 --额外点数每增长1 %。
VAR Growth = 0.001 -- 应用每100点后增长0.1 %
VAR GrowthRounded =
ROUNDDOWN ([% Groowth FYTD], 3 ) --舍入到接近0.1%
RETURN
IF(
GrowthRounded >0, -- 检查是否增长(>0)-- 定义0以上的增长点值
GrowthRounded * Points / Growth+ --将为超过1 %的所有销售再分配100分,计200分
MAX(
(GrowthRounded- GrowthRounded),0 ) – 如果增长率小于1%
* Points / Growth)
公式解释(VAR逻辑步骤)
(1) VAR --变量部分
在编写DAX公式时,常常需要多次的重复以及返工的过程,很少有一次性输入完整的、正确的公式的例子。 因此, 首先应为需要应用的每个业务规则编写对应的变量(上面公式的第2至6行)。但是,这肯定不只是简单的一个接一个地键入出每一行。
事实上,你需要将问题分解为一个个组件(或者说步骤),并最终使用Excel将它们构建成公式。如果你具有Excel版本的函数经验,那就更容易写出DAX公式了。
(2) RETURN--返回部分
注意,实际的DAX公式是从第7行开始(RETURN 之后)的。在第9行中,你可以看到第一个作为输入到最终公式中的一个变量引用(在本例中是GrowthRounded--增长的分值)。事实上,该公式已稍微改变了分配分值的逻辑方式。因为,似乎更容易的方法是:将100点值分配给所有高于0的销售额,然后再为所有超过1%销售额的那些行分配100点(相对于在0到1%之间分配了100点,然后再为销售额超过该点值(101%之后)的每超过0.1%的分配200点)。当然,所有这些在公式中都有明确的记录,所以,很清楚逻辑是什么、以及为什么这么定义。
希望你可以从这个示例进一步知道,VAR语法使编写能够被其他人读取、维护和理解,公式也变得很容易书写。
4、避免使用EARLIER
正如我前面提到的,在学习DAX时,EARLIER这个函数可能会有点让人迷茫。我们使用其中之一的解释是:EARLIER用于引用前一行筛选中的值。例如在“Adventure”工作薄的客户表中考虑下面2个计算列。(注意:不是说应该创建这样的列,这里只是用它们来演示EARLIER的用法)。
计算列1
Cust Sales = [Total Sales] --为客户表的每个客户添加了 [Total Sales]列。
计算列2
Customen Lifetime Rank = CALCULATE( Customers),
FILTER(Customers,
Customers[Cust Sales]>= EARLIER(Customers[Cust Sales]))
请注意公式第4行EARLIER的用法。该公式是一个计算列,所有计算列都有一个隐式行筛选。这里还有一个FILTER函数的行筛选:即第4行这个行筛选。因此,在这个公式中,实际上有两个嵌套的行筛选。它“筛选customer--客户表,只保留比目前正在考虑的这一个计算列中那些比当前销售额更大的客户行。这需要”EARLIER( ) 函数 “转移”FILTER函数的内部行筛选,并返回计算列创建的外部行筛选。这句话很拗口,但你所见的所有关于变量的解释都可能会用到这句话,因此不得不又拿出来。
这里需要两点理解:
第一,变量是存储数据,而公式计算需要引用原数据列表。也就是说,由于变量的特点,它除了更像 “常量”之外,也更像一个参数表(没有关系),因而,公式引用变量多半是使用变量的“常量”与参数表特性,来作为筛选,而不是计算(DAX=筛选+计算)。
第二,你可以将行筛选视为对表中每一行的迭代,以完成每行的相同任务。而且,可以根据需要,在某个行筛选中嵌套任意多的其他行筛选。
正如前文里提到的,可以使用VAR语法替代EARLIER函数,因为VAR语句在初始的行、列表筛选(计算筛选)中已进行了计算。这里是Customen Lifetime Rank 计算列的替代语法:
Customen Lifetime Rank =
VAR ThisCustomerSales = Customers[Cust Sales]
RETURN
CALCULATE ( COUNROWS(Customers),
FILTER(Customers,
Customers[Cust Sales]>=ThisCustomerSales)
这个新公式工作的原理是:第2行的VAR语句是在由FILTER函数创建的第二个行筛选之前计算的(它存在于FILTER筛选之前)。
本系列的变量部分到这里暂告一段落。