DAX содержит гибкие возможности фильтрации, и важными функциями являются ALL и REMOVEFILTERS. При использовании ALL и REMOVEFILTERS в качестве модификатора CALCULATE они ведут себя одинаково, т.к. в этом случае REMOVEFILTERS является псевдонимом ALL, однако ALL в FILTER возвращает «новую таблицу» и очищает влияние всех фильтров, что важно учитывать с точки зрения производительности и результатов.
Интересующимся особенностями ALL и сравнением ALL и REMOVEFILTERS — добро пожаловать под кат :)
Рассмотрим следующие вопросы с примерами на тестовых данных:
случаи, когда
ALLиREMOVEFILTERSэквивалентныпример
ALLвнутриFILTERс очисткой всех фильтров, что приводит к «созданию новой таблицы», а не просто к «снятию фильтра»детали отмены фильтрации по группировочным полям и фильтрам
FILTERвSUMMARIZECOLUMNSдляALLиREMOVEFILTERS
Рассмотрим все примеры на одном и том же наборе данных: схема с одной таблицей фактов sales и двумя справочниками product и customer.

Данные справочника клиентов customer:
customer_id |
customer_name |
customer_gender |
|---|---|---|
1 |
Mike Smith |
M |
2 |
John Doe |
M |
3 |
Mary Brown |
F |
Данные справочника продуктов product:
product_id |
product_name |
product_brand |
product_color |
|---|---|---|---|
1 |
Black Pen |
The First |
Black |
2 |
Red Pen |
The Best |
Red |
3 |
Blue Pen |
The First |
Blue |
4 |
White Pen |
The Second |
White |
5 |
Green Pen |
The First |
Green |
6 |
Silver Pen |
The Second |
Silver |
Данные таблицы фактов sales:
order_number |
customer_id |
product_id |
quantity |
amount |
orderdate |
|---|---|---|---|---|---|
0001 |
1 |
3 |
1 |
3.15 |
01-01-2025 |
0002 |
1 |
2 |
2 |
4.24 |
01-01-2025 |
0003 |
2 |
1 |
3 |
3.45 |
02-01-2025 |
0004 |
1 |
2 |
1 |
2.12 |
02-01-2025 |
0005 |
3 |
1 |
1 |
1.15 |
03-01-2025 |
0006 |
1 |
3 |
2 |
6.30 |
03-01-2025 |
0007 |
2 |
4 |
2 |
6.32 |
01-01-2025 |
0008 |
1 |
5 |
2 |
4.28 |
01-01-2025 |
0009 |
1 |
6 |
1 |
1.19 |
02-01-2025 |
0010 |
3 |
5 |
1 |
2.14 |
02-01-2025 |
0011 |
2 |
6 |
1 |
1.19 |
03-01-2025 |
0012 |
1 |
4 |
2 |
6.32 |
03-01-2025 |
Рассмотрим простейшую меру — сумму продаж:
Total Amount = SUM ( sales[amount] )
Каждый раз создавать новую меру не будем, будем лишь изменять выражение Total Sales в SUMMARIZECOLUMNS.
1. Исходный запрос с фильтрами по группировочным полям и FILTER в SUMMARIZECOLUMNS
Рассмотрим исходный запрос с тремя фильтрами: фильтр за счет группировки по цвету продукта product[product_color], фильтр за счет группировки по полу customer[customer_gender] и фильтр по полу customer[customer_gender]=M через FILTER в SUMMARIZECOLUMNS, причем product влияет на расчет Total Sales за счет группировочного поля product[product_color], а customer влияет на Total Sales за счет группировочного поля customer[customer_gender] и фильтра FILTER по полу M. Для упрощения фильтрацию по цвету продукта рассматриваем через FILTER, т.е. без TREATAS и других возможностей DAX.
EVALUATE
SUMMARIZECOLUMNS (
product[product_color],
customer[customer_gender],
FILTER ( customer, customer[customer_gender] = "M" ),
"Total Sales", CALCULATE ( SUM ( sales[amount] ) )
)

Видим результаты выполнения запроса, это поможет для интерпретации следующих кейсов.
2. ALL и REMOVEFILTERS как модификаторы CALCULATE
Рассмотрим ALL и REMOVEFILTERS по таблице в роли модификаторов CALCULATE. Это известный случай и понятно, что в нем REMOVEFILTERS является псевдонимом ALL, но это позволяет продемонстрировать работу ALL и REMOVEFILTERS наглядно.
Рассмотрим случаи удаления фильтра через ALL и REMOVEFILTERS для таблиц customer и product, результаты запросов совпадают для ALL и REMOVEFILTERS.
Удаление фильтра по customer с использованием ALL:
EVALUATE
SUMMARIZECOLUMNS (
product[product_color],
customer[customer_gender],
FILTER ( customer, customer[customer_gender] = "M" ),
"Total Sales", CALCULATE ( SUM ( sales[amount] ), ALL ( customer ) )
)
Удаление фильтра по customer с использованием REMOVEFILTERS дает те же результаты:
EVALUATE
SUMMARIZECOLUMNS (
product[product_color],
customer[customer_gender],
FILTER ( customer, customer[customer_gender] = "M" ),
"Total Sales", CALCULATE ( SUM ( sales[amount] ), REMOVEFILTERS ( customer ) )
)

Удаление фильтра по product через ALL:
EVALUATE
SUMMARIZECOLUMNS (
product[product_color],
customer[customer_gender],
FILTER ( customer, customer[customer_gender] = "M" ),
"Total Sales", CALCULATE ( SUM ( sales[amount] ), ALL ( product ) )
)
Удаление фильтра по product через REMOVEFILTERS дает те же результаты:
EVALUATE
SUMMARIZECOLUMNS (
product[product_color],
customer[customer_gender],
FILTER ( customer, customer[customer_gender] = "M" ),
"Total Sales", CALCULATE ( SUM ( sales[amount] ), REMOVEFILTERS ( product ) )
)

Таким образом, видно, что при использовании ALL и REMOVEFILTERS по таблице в роли модификаторов CALCULATE они возвращают одинаковые результаты.
3. FILTER со вложенным ALL возвращает таблицу и отменяет все существующие фильтры
Вложенный ALL в FILTER, в отличие от REMOVEFILTERS, возвращает таблицу и снимает все существующие фильтры. Соответственно, REMOVEFILTERS может работать только как модификатор CALCULATE, не возвращая новую таблицу.
Рассмотрим удаление фильтра по customer через ALL(customer) в FILTER:
EVALUATE
SUMMARIZECOLUMNS (
product[product_color],
customer[customer_gender],
FILTER ( customer, customer[customer_gender] = "M" ),
"Total Sales",
CALCULATE (
SUM ( sales[amount] ),
FILTER ( ALL ( customer ), customer[customer_gender] = "F" )
)
)

Для расчета выражения Total Sales при ALL(customer) в FILTER выполняются следующие шаги:
ALL(customer)создает «новую таблицу» без контекста, причем создаются связи таблиц на основе схемы данных, т.к.ALLумеет возвращать «новую таблицу»Снимаются все фильтры: фильтр по группировочной колонке
product_colorиз таблицыproduct, фильтр по группировочной колонкеcustomer[customer_gender]и фильтр по таблицеcustomerи полуMFILTERдля фильтрации по полуFработает по этой «новой таблице»«Новая таблица» из
ALLпосле фильтрации по полуF«присоединяется обратно» по группировочным полямproduct, дляcustomer— не присоединяется контекст фильтраSUMMARIZECOLUMNSпо полямcustomer, т.к. мы его удалили черезALL(customer). С точки зрения контекста фильтраSUMMARIZECOLUMNS— берем все цвета изproduct[product_color](т.к. фильтров по цвету вSUMMARIZECOLUMNSнет), но т.к. в выраженииTotal Salesесть фильтр поcustomerи считаем продажи поF, причем поFесть продажи только черных и зеленых продуктов, поэтому только дляBlackиGreenбудут записи, т.к. пустые результатыTotal Salesне выводятся. Для каждого значения группировочного поляproduct[product_color]из контекста фильтраSUMMARIZECOLUMNSполучаем разные значения продаж, причем считаем продажи поF, а выводим полM. С учетом возможности вывода только ненулевых значенийTotal Salesполучим толькоBlackиGreenпродажи для полаF, но подписанные какM.
Рассмотрим удаление фильтра по product через ALL(product) в FILTER:
EVALUATE
SUMMARIZECOLUMNS (
product[product_color],
customer[customer_gender],
FILTER ( customer, customer[customer_gender] = "M" ),
"Total Sales",
CALCULATE (
SUM ( sales[amount] ),
FILTER ( ALL ( product ), product[product_color] = "Green" )
)
)

Для расчета выражения Total Sales при ALL(product) в FILTER выполняются следующие шаги:
ALL(product)создает «новую таблицу» без контекста, причем создаются связи таблиц на основе схемы данных, т.к.ALLумеет возвращать «новую таблицу»Снимаются все фильтры: фильтр по группировочной колонке
product_colorиз таблицыproduct, фильтр по группировочной колонкеcustomer[customer_gender]и фильтр по таблицеcustomerи полуMFILTERдля фильтрации по цветуGreenработает по этой «новой таблице»«Новая таблица» из
ALLпо фильтрации по цветуGreen«присоединяется обратно» по группировочным полямcustomer, дляproduct— не присоединяем контекст фильтраSUMMARIZECOLUMNSпо полямproduct, т.к. мы его удалили черезALL(product). С точки зрения контекста фильтраSUMMARIZECOLUMNS— берем все цвета изproduct[product_color](т.к. фильтров по цвету нет), но поскольку в выраженииTotal Salesфильтр поproductсброшен черезALL(product), то для каждого значения группировочного поляproduct[product_color]из контекста фильтра получаем одно и то же значениеTotal Sales, равное4.28, что соответствует продажам по цветуGreenи полуM. Видно, что отображаемые в результатах цветаproduct_colorразные, ноTotal Salesсчитается только поGreen. Видно, что в этом запросе, в отличие от предыдущего, полMсоответствует результатам вTotal Sales, т.е. действительно отображаются продажи по полуM.
Вывод
В качестве модификатора в CALCULATE поведение ALL и REMOVEFILTERS одинаково и REMOVEFILTERS является лишь псевдонимом для ALL. Однако ALL в FILTER приводит к отмене всех фильтров и созданию «новой таблицы». Если интерпретировать несколько образно, то ALL в FILTER создает «новую вселенную» в данных, и затем движок DAX объединяет результаты с контекстом фильтра SUMMARIZECOLUMNS.
Надеюсь, приведенные выводы могут быть интересны, успешных дашбордов :-)