As variáveis foram introduzidas no DAX em 2015 e, até agora, provaram ser o melhor aprimoramento da linguagem DAX de todos os tempos. Quando apresentado ao conceito de variáveis, a maioria dos novatos se concentra na melhoria de desempenho, pensando que você introduz variáveis em seu código principalmente para obter melhor desempenho. Embora as variáveis possam melhorar o desempenho, o desempenho é uma vantagem menor. Há várias considerações mais importantes que devem encorajar qualquer desenvolvedor DAX a fazer uso extensivo de variáveis. Neste artigo, compartilhamos algumas considerações, juntamente com as práticas recomendadas sobre variáveis e DAX.
Comecemos pela sintaxe. Você pode definir uma variável em qualquer expressão DAX usando VAR seguido de RETURN. Em uma ou várias seções VAR, você declara individualmente as variáveis necessárias para calcular a expressão; na parte RETURN você fornece a própria expressão.
Esta fórmula simples inclui a definição de duas variáveis:
VAR SalesAmount = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) VAR NumCustomer = DISTINCTCOUNT ( Sales[CustomerKey] ) RETURN DIVIDE ( SalesAmount, NumCustomer )
A variável SalesAmount contém o valor em dólares das vendas calculadas por meio de SUMX , enquanto a variável NumCustomer contém o número de clientes, como o DISTINCTCOUNT de Sales[CustomerKey] .
As duas variáveis são usadas na parte RETURN, onde dividimos uma pela outra. O resultado de toda a expressão é a parte RETURN.
Você pode pensar em uma variável como um nome para uma expressão. O próprio termo “variável” é um tanto enganoso – uma variável DAX não pode alterar seu valor, como o nome sugere. Uma variável DAX é de fato uma constante , o que significa que é um nome para o valor calculado pela definição da variável.
Cada conjunto de VAR/RETURN pode incluir múltiplas variáveis, você pode ter qualquer número de VAR para um RETURN. Além disso, a definição de uma variável pode fazer referência a outras variáveis, desde que as outras variáveis tenham sido definidas de antemão – dentro do mesmo bloco ou em um bloco externo. Como esta última instrução sugere, as instruções VAR podem ser aninhadas. Por exemplo, a expressão anterior pode ser escrita usando mais variáveis da seguinte maneira bastante detalhada:
Medida na tabela Vendas
6SalesPerCustomer := VAR SalesAmount = SUMX ( Sales, VAR Quantity = Sales[Quantity] VAR Price = Sales[Net Price] RETURN Quantity * Price ) VAR NumCustomer = DISTINCTCOUNT ( Sales[CustomerKey] ) RETURN DIVIDE ( SalesAmount, NumCustomer )
As variáveis Quantidade e Preço não são realmente úteis neste exemplo. No entanto, eles ajudam a mostrar que você pode definir variáveis em qualquer lugar em uma fórmula DAX. O conjunto VAR / RETURN substitui uma expressão, portanto pode ser usado onde quer que uma expressão seja permitida. Esta não é uma técnica muito comum. Na maioria das vezes, você verá uma fórmula DAX contendo um conjunto inicial de declarações de variáveis, seguidas por uma única instrução RETURN. Independentemente disso, há casos em que, para códigos bastante complexos, o uso generoso de VAR / RETURN é útil.
As variáveis são úteis por vários motivos:
Legibilidade do código. Ao atribuir um nome a uma expressão, você está efetivamente adicionando informações descritivas ao seu código, facilitando sua leitura.
Divisão da execução em etapas lógicas. Nosso cérebro processa melhor as expressões que contêm variáveis, porque as variáveis fornecem etapas de execução. No código anterior, você pode pensar que SalesAmount é calculado primeiro, depois NumCustomer e, finalmente, o resultado. Apesar disso não ser verdade, as variáveis ainda ajudam a ler e entender o código.
Depuração mais fácil do código. Você pode inspecionar o valor das variáveis usando depuradores profissionais, como o depurador Tabular Editor 3, ou pode retornar o valor de uma variável em uma medida complexa para inspecionar as avaliações intermediárias.
Melhor performance. Usando variáveis, você instrui o otimizador DAX sobre quais partes da expressão inteira podem ser calculadas uma vez e salvas para uso posterior. O valor de uma variável é computado apenas uma vez, enquanto repetir a mesma subexpressão em vários lugares não garante uma execução única daquele pedaço de código.
Embora os novatos não usem muitas variáveis, os desenvolvedores DAX experientes se acostumam a iniciar a maioria das medidas com VAR! A razão é que qualquer medida não trivial requer etapas diferentes e, ao dividir todo o cálculo em etapas, eles podem se concentrar melhor em problemas mais simples. Em termos de mindset, faz muita diferença começar a pensar em um cálculo complexo com esta frase: “Primeiro preciso de uma variável com esse valor, depois vou focar nos próximos passos”.
Poderíamos fornecer vários exemplos de código que são mais legíveis com variáveis do que sem variáveis. No entanto, esses seriam apenas exemplos ad-hoc. Acreditamos que a melhor maneira de avaliar o quanto nós do SQLBI valorizamos a relevância das variáveis é navegar em nossos artigos. Usamos variáveis em todos os lugares, por boas razões.
Um detalhe importante sobre variáveis, embora não esteja claro à primeira vista, é que as variáveis também podem conter tabelas. Embora seja intuitivo considerar uma variável para um valor escalar, é menos intuitivo também considerar variáveis quando se deseja armazenar tabelas.
Veja, por exemplo, a seguinte parte do código DAX:
Medida na tabela Vendas
Best Product Sales := VAR BestProducts = TOPN ( 10, Product, [Sales Amount] ) VAR SalesOfBestProducts = SUMX ( BestProducts, SUMX ( RELATEDTABLE ( Sales ), Sales[Quantity] * Product[Unit Price] ) ) RETURN SalesOfBestProducts
Há várias considerações importantes a serem feitas sobre esse pequeno trecho de código.
A primeira é que você o lê como duas etapas separadas: você pensaria que o DAX primeiro calcula a variável BestProducts e, em seguida, executa uma iteração sobre seu conteúdo enquanto calcula a segunda variável, SalesOfBestProducts . Como dissemos, isso não é verdade; O DAX usa um padrão de execução diferente. No entanto, ajuda a entender o fluxo.
A variável BestProducts contém o resultado de TOPN , que é uma tabela. BestProducts contém os 10 principais produtos pedidos por Sales Amount . BestProducts é uma variável de tabela.
Durante a avaliação da variável SalesOfBestProducts , a medida itera sobre BestProducts . Em seguida, para cada linha de BestProducts , a medida varre as vendas relacionadas, durante o SUMX sobre RELATEDTABLE . RELATEDTABLE requer relacionamentos para funcionar. Na verdade, uma variável que contém uma tabela herda os relacionamentos das tabelas base das colunas que ela contém. Como BestProducts contém linhas de Product , ele herda o relacionamento entre Product e Sales . Portanto, RELATEDTABLE funciona muito bem.
A segunda consideração não trivial é que o SUMX mais interno calcula Sales[Quantity] vezes Product[Unit Price] . Sales está no contexto de linha, introduzido pelo SUMX mais interno . O produto parece não estar no contexto da linha – o SUMX mais externo está iterando BestProducts . Parece intuitivo referir-se à coluna Unit Price em BestProducts como BestProducts[Unit Price] . Infelizmente, esta sintaxe não está disponível. Para referenciar uma coluna dentro de uma variável, você precisa referenciar o nome da coluna com o prefixo da tabela base. Assim, ao invés de usarBestProducts[Unit Price] , você precisa usar Product[Unit Price] .
No caso muito especial em que uma coluna pertence a uma variável, mas é criada dentro da medida, digamos usando ADDCOLUMNS , você não pode especificar um nome de tabela. Este é o único caso em que nossas regras muito rígidas sobre legibilidade permitem que o desenvolvedor faça referência a uma coluna sem o nome da tabela prefixado, em vez de usar a sintaxe formalmente corrigida, mas menos legível ”[coluna] usando um nome de tabela vazio como prefixo.
O último detalhe importante sobre as variáveis é que elas representam um determinado valor quando são definidas e nunca mais são calculadas novamente. Em nossos cursos auxiliamos com inúmeras dúvidas de desenvolvedores DAX que não entendem porque substituir uma expressão por uma variável altera o resultado. Considere, por exemplo, a seguinte medida:
Medida na tabela Vendas
Pct := DIVIDE ( SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ), CALCULATE ( SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ), ALL ( Product ) ) )
A expressão SUMX aparece duas vezes, idêntica. Parece um bom candidato para uma variável. Infelizmente, não é. Se você alterar o código introduzindo uma variável, a medida calculará um resultado incorreto:
Medida na tabela Vendas
Pct (Wrong) := VAR SalesAmount = SUMX ( Sales, Sales[Quantity] * Sales[Net Price] ) RETURN DIVIDE ( SalesAmount, CALCULATE ( SalesAmount, ALL ( Product ) ) )
PCT (Errado) retorna um valor constante de 1. O motivo é que a variável SalesAmount é calculada uma vez e nunca mais. Não importa que a segunda referência a SalesAmount esteja dentro de um CALCULATE que remove o filtro de Product . Seu valor já foi calculado e não muda dependendo do contexto do filtro. Você pode substituir subexpressões por variáveis, mas somente se tiver verificado se as subexpressões são calculadas no mesmo contexto de filtro.
Durante nossos cursos, na hora de falar sobre variáveis, fornecemos uma regra simples: sempre que você estiver em dúvida se deve definir ou não uma variável, defina a variável. A resposta para a pergunta: “é melhor escrever o código ou usar uma variável aqui?” deve ser sempre criar uma variável.
Existem alguns cenários muito específicos em que uma variável pode realmente impactar negativamente o desempenho, porque às vezes força uma avaliação ansiosa de declarações condicionais. Eles são raros, portanto, nossa sugestão para novos desenvolvedores DAX é usar o máximo de variáveis possível. Com o tempo, seu futuro eu agradecerá porque você usou tantas variáveis e tornou o código muito mais fácil de ler.