Quelle est la différence entre les résultats de la fonction CALCULATE
si nous l’utilisons avec et sans la fonction FILTER. Supposons que nous ayons ces deux mesures:
Measure1 = CALCULATE([X], 'FactTable'[Color]="Red")
Measure2 = CALCULATE([X], FILTER('FactTable', 'FactTable'[Color]="Red")
Mettre à jour. Question de prime supplémentaire:
Existe-t-il un moyen de modifier Measure2 à l’aide d’autres fonctions, telles que ALL
ou ALLSELECTED
, pour qu’il renvoie exactement les mêmes résultats que Measure1?
Mise à jour après la prime
J'ai décidé d’accorder la prime pour une réponse différente de celle que j’ai acceptée.
Non seulement les résultats, mais aussi la manière d'obtenir ces résultats pour les deux mesures ne seront pas les mêmes.
J'ai créé deux mesures similaires à votre exemple pour tester ceci:
TestAvgNoFilter = CALCULATE([PrcAvg]; cal[ReadDate]=DATE(2018;05;23))
TestAvgFilter = CALCULATE([PrcAvg]; filter(cal; cal[ReadDate]=DATE(2018;05;23)))
Lorsque je jette simplement les deux dans un tableau croisé dynamique sans champs ni trancheurs supplémentaires, bien sûr, les deux montrent le même résultat:
Toutefois:
L'utilisation de FILTER
a un impact significatif sur les performances, ce qui se voit clairement dans les plans de requête et l'utilisation de Storage Engine par rapport à Formula Engine. Il crée une table temporaire supplémentaire qui doit "interagir" avec les filtres déjà existants provenant du rapport/tableau croisé lui-même (lignes, colonnes, découpeurs). Vous ne remarquerez rien pour la valeur moyenne simple dans une seule cellule, mais si votre mesure [x] est compliquée et qu'il existe de nombreux filtres "initiaux", la différence de temps de calcul peut être énorme.
FILTER
conserve et iteracts avec le contexte de filtre initial, tandis que l'expression de filtre utilisée directement dans CALCULATE
l'ignore. Voyez ce qui se passe lorsque j'ajoute ReadDate au tableau croisé dynamique:
C'est précisément pourquoi la mesure sans FILTER
est plus rapide: peu importe les dates dans les colonnes - elle a déjà calculé une valeur "vraie", tandis que la mesure avec FILTER
s'autoévalue par rapport aux filtres initiaux pour chaque ligne.
Les résultats des deux colonnes peuvent être considérés comme corrects - tout dépend en réalité de l'interprétation et du nom des mesures;).
En règle générale, je vous conseillerais de ne pas utiliser FILTER
lorsque vous n'êtes pas obligé de le faire. Économisez sa puissance pour quand c'est vraiment nécessaire.
La différence ici est que CALCULATE
permet des filtres simples qui remplaceront le contexte de filtre existant. Dans votre exemple, CALCULATE
calculera la mesure [X]
en utilisant le contexte de filtre existant, sauf qu'elle supprime tout contexte de filtre existant pour FactTable[Color]
et le remplace par FactTable[Color] = Red.
.
La fonction FILTER
est un itérateur, ce qui signifie qu’elle parcourt la table (transmise comme premier argument) ligne par ligne et évalue l’expression (second argument) de chaque ligne. Lorsque vous avez une fonction FILTER
à l'intérieur de CALCULATE
, elle combine le contexte de filtre existant avec les résultats de FILTER
(au lieu de le remplacer comme un simple argument de filtre).
En général, vous voulez utiliser des filtres simples chaque fois que vous avez le choix, car le calcul sera plus efficace. Cependant, la fonction FILTER
vous permet d'effectuer un filtrage beaucoup plus complexe. Elle est donc très utile dans les cas où les filtres simples ne suffisent pas.
Lectures supplémentaires: FILTER () - Quand, pourquoi et comment l'utiliser
La syntaxe DAX de la fonction automatique FILTER générée par DAX à la place d'une expression logique nécessite que vous exprimiez une seule colonne dans l'expression de filtre. Prenons cet exemple -
Measure1 = CALCULATE([X], 'FactTable'[Color]="Red")
La syntaxe ci-dessus est transformée en interne dans la suivante, que vous pourriez écrire de manière explicite en obtenant le même comportement depuis votre mesure DAX.
Measure1 = CALCULATE([X], FILTER(ALL('FactTable'[Color]), 'FactTable'[Color]="Red"))
Donc, si vous utilisez la dernière fonction de la valeur Measure2, le même résultat sera obtenu.