本篇文章将介绍ALLEXCEPT函数的使用,ALLEXCEPT函数的使用频率没有ALL函数高,但在某些情况下却是很有用的。当我们需要移除多个筛选器并保留少数筛选器时,使用ALLEXCEPT函数能够大大减少代码的书写量。


  ALLEXCEPT函数的语法结构

  • 语法:
ALLEXCEPT ( <TableName>, <ColumnName>, [ <ColumnName>, [ … ] ] )
  • 作用:

  ALLEXCEPT函数也有两种用法,一种是用作表函数,另一种则是用作筛选调节器。ALLEXCEPT函数的具体作用如下:

  1、若ALLEXCEPT用作表函数时,将返回第一参数的表中除所指定的列之外的所有列的现有值的唯一值组合,忽略任何筛选器。

  2、若ALLEXCEPT用作筛选调节器时,将移除第一参数指定的表的扩展表中除所指定列之外的其余列上的所有筛选器。

  先对ALLEXCEPT函数的接受的参数做一个简单的介绍。ALLEXCEPT函数的第一参数必须为基础表,第二参数可以是一个或多个列,这些列必须来自第一参数所指定的基础表的扩展表上的列。


  本篇文章使用到的数据与数据模型如下图所示:


  将ALLEXCEPT函数用作表函数

  当ALLEXCEPT函数用作表函数时,将返回第一参数的表中除所指定的列之外的所有列的现有值的唯一值组合。为了更好地理解这句话,下面用一个简单的例子来描述:假设有一个表具有四列,列名分别为:A、B、C、D,那么当ALLEXCEPT函数的第二参数指定了A列,那么将把BCD三列完整提取出来形成一个表,然后再对这个表按行为单位进行去重,然后ALLEXCEPT函数返回这个表去重后的结果。

  其实上面的这个简单例子可以用ALL函数等价表示出来,即:

// 该等价写法只在ALLEXCEPT函数用作表函数时等价

ALLEXCEPT('TableName','TableName'[ColumnName1])

----------------假设表只有四列,那么ALLEXCEPT等价于---------------

ALL('TableName'[ColumnName2],'TableName'[ColumnName3],'TableName'[ColumnName4])

  下面来看一些帮助理解的例子,为了方便起见,使用查询来进行演示:

  上面介绍的例子可以结合上面给出的等价写法进行理解,下面来看一个比较特殊的情况。之前介绍ALLEXCEPT函数的语法结构时曾说过,ALLEXCEPT函数的第二参数可以是来自第一参数的基础表的扩展表上的列,那么在ALLEXCEPT函数用作表函数时,若其第二参数所指定的列来自于扩展表上不属于基础表自身列之外的其他列,那么ALLEXCEPT将返回第一参数所指定的基础表按行去重后的结果,忽略任何筛选器,即类似于使用ALL函数引用基础表所有列时的情况。


  将ALLEXCEPT函数用作筛选调节器

  当ALLEXCEPT函数用作筛选调节器时,将移除第一参数指定的表的扩展表中除所指定列之外的其余列上的所有筛选器。这句话的意思其实很直白,但由于定语过多可能会比较难读懂,因此多读几次就好了。ALLEXCEPT函数用作筛选调节器时也是移除筛选器,因此只需要了解清楚它会移除哪些筛选器即可,下面就以一个简单例子来描述ALLEXCEPT函数的行为。

  假设现有一个表A,它有四个列,列名分别为:A1、A2、A3、A4;而表A有一个上级表,该上级表名为表B,它有三个列,列名分别为:B1、B2、B3;此外,表A还有一个下级表,该下级表名为表C,它有两个列,列名分别为C1、C2。表间关系可以简单描述为:表B—>表A—>表C,关系都是一对多关系。

  然后,假设外部计值环境中存在四个筛选器,筛选的列分别为:A1、B1、B2、C1,那么ALLEXCEPT函数用作筛选调节器时的不同写法与行为如下:

  1、ALLEXCEPT(表A,A1),将移除表A的扩展表上除A1列外的其它列上的筛选器,因此,B1、B2筛选器被移除,A1、C1筛选器保留

  2、ALLEXCEPT(表A,A4),将移除表A的扩展表上除A4列外的其它列上的筛选器,因此,A1、B1、B2筛选器被移除,C1筛选器保留

  3、ALLEXCEPT(表B,B1),将移除表B的扩展表上除B1列外的其它列上的筛选器,因此,B2筛选器被移除,A1、B1、C1筛选器保留

  4、ALLEXCEPT(表B,B1,B2),将移除表B的扩展表上除B1与B2列外的其它列上的筛选器,因此,A1、B1、B2、C1筛选器均保留

  5、ALLEXCEPT(表B,B3),将移除表B的扩展表上除B3列外的其它列上的筛选器,因此,B1、B2筛选器被移除,A1、C1筛选器保留

  6、ALLEXCEPT(表C,A1),将移除表C的扩展表上除A1列外的其它列上的筛选器,因此,B1、B2、C1筛选器被移除,A1筛选器保留

  7、ALLEXCEPT(表C,A3),将移除表C的扩展表上除A3列外的其它列上的筛选器,因此,A1、B1、B2、C1筛选器均被移除

  上面举的七个小例子都是常规性用法,非常规性用法就是用表作为ALLEXCEPT函数的第二参数,虽然用表作为第二参数的用法在官方文档的语法结构里没有给出,但其实也是支持的,算是隐藏用法吧。当用表作为ALLEXCEPT函数的第二参数时,该表可以是第一参数所指定的基础表的任意一个上级表。下面仍然使用上面例子中的数据来描述一下这种非常规性用法时ALLEXCEPT函数的行为:

  1、ALLEXCEPT(表A,表B),将移除表A的扩展表上除B1、B2、B3列外的其它列上的筛选器,因此,A1筛选器被移除,B1、B2、C1筛选器保留

  2、ALLEXCEPT(表A,表B,A1),将移除表A的扩展表上除B1、B2、B3、A1列外的其它列上的筛选器,因此,A1、B1、B2、C1筛选器均保留

  3、ALLEXCEPT(表C,表B),将移除表C的扩展表上除B1、B2、B3列外的其它列上的筛选器,因此,A1、C1筛选器被移除,B1、B2筛选器保留

  4、ALLEXCEPT(表C,表A),将移除表C的扩展表上除A1、A2、A3、A4、B1、B2、B3列外的其它列上的筛选器,因此,C1筛选器被移除,A1、B1、B2筛选器保留


  由于ALLEXCEPT函数涉及到了扩展表,因此显得比较抽象,不太好用具体的实际例子去表达,所以我觉得用上面这种描述方式可能效果会更好。但这样描述的一个缺点就是说服力不够强,但上面给出的各种情况的结果我都已经检查过多遍了,如果我的理解没有错误那么这都是正确的结果。当然,如果你信不过我,那也可以自己去测试,这都是没问题的。甚至,如果你发现我出错了,那么我非常欢迎你指出我的错误,因为这样就代表着我的理解是有误的,那么我也可以借着纠正错误的机会让技术更进一步。


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

  加入Q群