У меня есть следующий файл PowerBI с двумя таблицами.
Формула 100 рядов против 50 рядов
Одна из таблиц содержит 50 строк, а другая — 100 (обе таблицы имеют одинаковые значения, меняется только количество повторяющихся строк).
У меня также есть следующая формула:
Indis = SUMX(
FILTER( ‘Table50rows’,
‘Table50rows’[cfId] = 10029 ),
VALUE(‘Table50rows’[fieldValue])
)
Проблема в том, что формула корректно работает с таблицей из 50 строк, но с таблицей из 100 строк выдает следующую ошибку:
MdxScript(Model) (17,5) Ошибка вычисления меры: невозможно преобразовать значение «N0» типа «Текст» в тип «Число».
Это странно, и мне было бы интересно услышать мысли других. Я также хотел бы обсудить этот вопрос с Microsoft, поскольку ее поведение странное. Кстати, отсечение составляет 65 строк (64 работает нормально, а 65 вызывает проблему). Даже использование слайсера не имеет никакого значения.
Может ли это быть связано с нетерпеливой строгой оценкой в SUMX()? Понятия не имею, и мне были бы интересны другие теории (далее читайте: https://www.sqlbi.com/articles/understanding-eager-vs-strict-evaluation-in-dax/).
Для справки, это заставляет вашу меру работать:
Indis_2 =
VAR x =
FILTER(
'Table100rows',
'Table100rows'[cfId] == 10029
)
VAR y = ADDCOLUMNS(x, "@test", 1)
RETURN
SUMX(
y,
VALUE('Table100rows'[fieldValue])
)
Простое принудительное вычисление фильтра путем добавления фиктивного столбца означает, что мера теперь работает.
Самый простой обходной путь, который я нашел, — просто добавить IFERROR(VALUE(‘Table100rows’[fieldValue]), 0)
и игнорировать строки, выдающие ошибку в SUM.
Да, это еще один вариант. Реальный вопрос в том, почему это вообще происходит. Фильтр должен содержать только одну строку и не выдавать никаких ошибок.
Я разговаривал с Джеффри Вангом (отцом DAX), и он дал окончательный ответ. Цитируется ниже с его разрешения:
Это связано с разными стратегиями выполнения Vertipaq Engine. это не гарантирует, что VALUE() вызывается после предложенияwhere. Чтобы гарантировать, что VALUE() вызывается только в безопасных случаях, используйте SUMX(..., IF()) шаблон: SUMX('Table100rows', IF('Table100rows'[cfId] = 10029, ЗНАЧЕНИЕ('Таблица100строк'[полеЗначение])))
Это относится ко всем выражениям агрегации, передаваемым в Vertipaq. Двигатель. Выражения агрегирования не должны предполагать, что где пункт применяется первым; вместо этого они должны обеспечить свою собственную безопасность во время исполнения. Я не подразумеваю, что выражения агрегации будут оцениваться во время выполнения, игнорируя предложениеwhere, которое явно проблема с производительностью. Просто выражение может быть оценивается на этапе подготовки Vertipaq Engine относительно некоторых значения без применения предложенияwhere.
Кажется странным, что официальная документация SUMX не упоминает об этом, учитывая, что они используют пример SUMX(FILTER(InternetSales, InternetSales[SalesTerritoryID]=5),[Freight])
, который также должен выдавать ошибку.
Да, но на официальных страницах справки MS есть много недокументированных сведений о DAX. В результате SQLBI обновила DAX.guide.
Это определенно странно. Я не вижу никакой разницы в планах запросов или кодировках столбцов и не знаю, что еще искать.