本篇文章将简单介绍一些有益的书写规范,以及DAX中的绝大部分基础函数,这些基础函数都是从Excel中继承过来的,与DAX原理的相关度比较低,易于学习。如果你已经对Excel公式很熟悉,那么简单过一遍即可,否则建议熟悉完基础函数后再进行后续的学习。


  下面先来看一下DAX中各个对象的书写规范:

  • 各个对象的名称不区分大小写,标点符号必须为英文状态下的符号

  • 表的引用方法:’TableName’

  • 度量值的引用方法 :[MeasureName],虽然把表名带上也不会出错,但非常不建议度量值带表名
  • 列的引用方法:
    • 完全限定性写法 :’TableName’[ColumnName]
    • 非限定性写法 :[ColumnName],只适用于存在行上下文的环境
  • 字符串的表示方法:”String”
  • 注释符号:
    • //
    • /*………*/
    • 快捷键:Ctrl+/

  从上面的书写规范中可以看出,度量值与列的引用方法都是可以带表名或不带表名的,若两者均带上表名或均不带表名,那么在一个比较复杂的DAX表达式中,将很难判断哪个是度量值引用、哪个是列的引用,这样就给我们阅读DAX表达式带来了不必要的麻烦。所以我们有一个约定俗成的书写规则,即:度量值的引用不带表名,而列的引用则带表名。这样,我们就可以轻松判断出两者的类别,能够把精力更专注于表达式的逻辑中。

  其次,我们应该使用一种便于阅读DAX表达式的格式化风格,在介绍格式化的风格之前,先来看一下未格式化与格式化后的DAX表达式对比:

// 这是未格式化的DAX表达式:

SUMX(SUMMARIZE('T3销售','日期表'[Date],'T0大类'[T0大类K]),IF([Sales]<>BLANK(),VAR CurrentDay = '日期表'[Date]
VAR LastDay = LASTNONBLANK(FILTER(ALL('日期表'[Date]),'日期表'[Date]<CurrentDay),[Sales]) RETURN CALCULATE([Sales],LastDay)))
// 这是格式化后的DAX表达式:

SUMX (
    SUMMARIZE ( 'T3销售', '日期表'[Date], 'T0大类'[T0大类K] ),
    IF (
        [Sales] <> BLANK (),
        VAR CurrentDay = '日期表'[Date]
        VAR LastDay =
            LASTNONBLANK (
                FILTER ( ALL ( '日期表'[Date] ), '日期表'[Date] < CurrentDay ),
                [Sales]
            )
        RETURN
            CALCULATE ( [Sales], LastDay )
    )
)

  我们先不管上面的DAX表达式的逻辑,只从易于阅读的角度来观察。那么在上面的对比中我们可以发现,未格式化的DAX表达式是不易于阅读的,它的各个函数以及参数均不容易区分,而格式化后的DAX表达式则没有这个缺点,是易于阅读的。因此,我们应该统一使用一种便于阅读的格式化风格。格式化风格之间的差异并不重要,只要这种格式化风格是便于你自己阅读你所写的DAX表达式的即可。

  虽然格式化风格可以多种多样,但为了方便与各个DAX的学习者交流,我们一般都是采用两位意大利大师所给出的格式化规则,这也是DAX Studio所采用的规则,具体如下:

  • 切勿使用缩短的CALCULATE语法
    • 这意味着不要使用[measure](filter)而是使用CALCULATE([measure],filter)
  • 总是在括号’(’和’)’前加一个空格
  • 始终在表达式中的任何操作数和运算符之前放置一个空格
  • 如果必须将表达式拆分成更多行,则运算符是换行符中的第一个字符
  • 拆分为更多行的表达式中的函数调用必须始终位于新行中,并在前面加上运算符
  • 切勿在表名和列名之间放置空格
  • 如果需要,仅对表名使用单引号
    • 因此,如果表名没有空格,请省略单引号
  • 切勿将表名称用于度量
  • 始终使用表名称作为列引用
    • 即使您在表中定义计算列
  • 如果在同一行中,请始终在参数前放置一个空格
  • 仅当函数具有单个参数而不是函数调用时,才编写函数内联
  • 如果函数调用具有2个或更多参数,则始终将参数放在新行上
  • 如果函数写在更多行上:
    • 左括号’(’在函数调用的同一行
    • 参数以换行符开头,从函数调用的开头缩进4个空格
    • 右括号与函数调用的开始对齐
    • 分隔两个参数的逗号在前一个参数的同一行(之前没有空格)

规则来源:https://www.sqlbi.com/articles/rules-for-dax-code-formatting/


  下面介绍一些常用的基础函数:

  • 时间日期函数:
函数 作用
DATE 返回日期时间格式的日期值
DATEVALUE 将文本格式的日期转换为日期时间格式
EDATE 返回按指定月数平移后的日期
EOMONTH 返回指定月数平移后的月份的最后一天
YEAR 返回日期的年份
QUARTER 返回日期的季度
MONTH 返回日期的月份
DAY 返回日期的天数
WEEKDAY 返回当前日期对应的星期数,ReturnType=2 以周一为起始
WEEKNUM 返回当前日期位于一年中的周数,ReturnType=2 以周一为起始
TIME 将数字形式的小时、分钟和秒转换为日期时间格式
TIMEVALUE 将文本格式的时间转换为日期时间格式
NOW 返回当前日期和时间
TODAY 以日期时间格式返回当前日期
HOUR 返回时间的小时
MINUTE 返回时间的分钟
SECOND 返回时间的秒
  • 文本函数
函数 作用
FIND 查找一个字符串在另一个字符串里的起始位置,区分大小写,不支持通配符
SEARCH 查找一个文本字符串在另一个字符串里的起始位置,不区分大小写,支持通配符
LEFT 从一个字符串的左边开始提取字符
RIGHT 从一个字符串的右边开始提取字符
MID 从一个字符串的任意位置开始提取字符
LEN 返回字符串的长度
CONCATENATE 字符串连接
REPLACE 将字符串的某些字符用另一个字符串代替
SUBSTITUTE 用一个字符串去替换另一个字符串的特定字符
LOWER 将字符串全部小写
UPPER 将字符串全部大写
TRIM 删除字符串前后多余的空格
VALUE 将文本型数字转换为数值型数字
  • 数学函数
函数 作用
ABS 返回绝对值
DIVIDE 安全除法,在分母为0时可返回替代结果,默认空值
EXP 返回自然常数 e 的给定数字次方
LN 自然对数
LOG 返回指定底数的对数
LOG10 返回以十为底的对数
MOD 返回指定数字被整除后的余数
POWER 返回提升到幂的数字的结果
SQRT 返回给定数字的平方根
FACT 返回给定数字的阶乘
RAND 返回一个大于等于 0 且小于 1 的均匀随机数
RANDBETWEEN 返回指定数字之间的随机数
PI 返回圆周率
  • 转换函数
函数 作用
CONVERT 将表达式转换为指定的数据类型,可转换为整数,双精度,字符串,布尔值,货币,日期时间类型
INT 将表达式转换为整数(向下舍入)
TRUNC 通过删除数字的小数或小数部分将数字截断为整数
ROUND 将数字四舍五入为指定的数字
DATE 返回日期时间格式的日期值
DATEVALUE 将文本格式的日期转换为日期时间格式
TIME 将数字形式的小时、分钟和秒转换为日期时间格式
TIMEVALUE 将文本格式的时间转换为日期时间格式
VALUE 将文本型数字转换为数值型数字
FORMAT 将值转换为指定数字格式的文本
  • 逻辑函数
函数 作用
IF (condition,true,false) 条件判断语句
SWITCH 根据表达式的值返回不同的结果。
AND() 逻辑与
OR () 逻辑或
NOT () 逻辑非
TRUE () 逻辑真
FALSE () 逻辑假
IFERROR 判断是否出错
  • 信息函数
函数 作用
ISBLANK 检查值是否为空
ISEMPTY 检查表是否为空
ISERROR 检查值是否为错误
ISLOGICAL 检查是否为逻辑值
ISNONTEXT 检查是否为非文本
ISNUMBER 检查是否为数值
ISTEXT 检查是否为文本
  • 聚合函数
函数 作用
SUM 求和
AVERAGE 求平均
MAX 最大值
MIN 最小值
COUNT 对数值计数
COUNTA 对非空数据计数
COUNTROWS 计算表的行数
COUNTBLANK 计算列中的空值个数
DISTINCTCOUNT 计算去重后的数据个数
STDEV.P 求总体标准差
STDEV.S 求样本标准差
VAR.P 求总体方差
VAR.S 求样本方差
PRODUCT 返回列中的数的乘积

  DAX系列文章中涉及到的案例文件,均已上传到QQ群:344353627,若有需要,可自行加群获取。

  加入Q群