DAX中ALLSELECTED()与FILTER()搭配使用的作用及相关语法疑问
1. ALLSELECTED的作用及FILTER不会被忽略的原因
你对ALLSELECTED的定义理解存在小偏差:CALCULATE的多个筛选参数是**逻辑与(交集)**的关系,不存在后面的参数覆盖前面参数的规则。
不带参数的ALLSELECTED()作用是:清除当前查询上下文里,来自视觉对象行/列维度等内部生成的筛选,仅保留用户在报表层面(切片器、页面/报表级筛选)选择的外部筛选。它的清除范围不包含CALCULATE自身参数里新增的筛选条件。
用SQL类比的话:你把「中心名称」放到了表格的行维度,那每行默认会自带WHERE center.name = '当前行中心名'的条件,ALLSELECTED()就是先把这一类自动生成的WHERE条件删掉,只保留你在切片器里手动选择的条件(比如WHERE region = '华东')。而前面的FILTER('Center', NOT 'Center'[Acc] IN {"RSM", BLANK() })是在清理后的上下文上,额外新增center.acc NOT IN ('RSM', NULL)的WHERE条件,完全不会被ALLSELECTED影响。
2. VALUES作为CALCULATE筛选参数的作用
CALCULATE的筛选参数支持所有返回表结构的表达式,本质是把返回的表内容作为筛选范围,和其他筛选条件取交集。VALUES('Customer'[Customer Number])返回的是原始上下文中所有被选中的客户编号去重列表,放在CALCULATE参数里的作用,相当于新增一个筛选条件:customer.customer_number IN (当前上下文选中的客户编号列表)。
用SQL类比的话,等价于先查询一个临时表:
WITH tmp_cust AS (SELECT DISTINCT customer_number FROM customer WHERE 【原始上下文带的客户筛选条件】)
然后在主查询的WHERE子句中新增AND customer.customer_number IN (SELECT customer_number FROM tmp_cust)。这个参数的常见作用是给ALLSELECTED加例外:其他维度的内部筛选可以清除,唯独客户编号的筛选要保留。
3. DAX语句的最终返回结果
CALCULATE的第一个参数是核心计算表达式,后面所有参数都是用来控制计算范围的筛选条件,所以最终返回的是所有筛选条件都满足的Revenue[Net]列的求和结果,VALUES只是筛选条件之一,不会作为返回值输出。
用SQL类比的话,整个DAX的逻辑等价于:
SELECT SUM(revenue.net) AS result FROM revenue LEFT JOIN center ON revenue.center_id = center.center_id LEFT JOIN customer ON revenue.customer_id = customer.customer_id WHERE -- ALLSELECTED保留的用户手动选择的外部筛选 【切片器/报表级筛选条件,如year = 2023】 -- FILTER参数新增的中心筛选 AND center.acc NOT IN ('RSM', NULL) -- VALUES参数新增的客户筛选 AND customer.customer_number IN (SELECT DISTINCT customer_number FROM customer WHERE 【原始上下文的客户筛选】)
内容的提问来源于stack exchange,提问作者Chicago1988

