TOTALYTD, SAMEPERIODLASTYEAR e DATEADD resolvem um problema direto: comparar um número com o mesmo número em outro período, sem reescrever a lógica de filtro de data toda vez que uma medida precisa de uma variação YTD, MoM ou YoY.
O problema é que alguns dos analistas as trata como três receitas intercambiáveis — e é aí que a medida retorna em branco, o número bate errado no fechamento, ou o modelo fica lento demais para ser usado com DirectQuery.
Essas três funções não são independentes umas das outras. TOTALYTD é, tecnicamente, um atalho para outra combinação de funções. SAMEPERIODLASTYEAR, internamente, é uma forma específica de DATEADD.
Entender essa relação — e principalmente onde ela deixa de valer — é o que separa quem escreve uma medida de Time Intelligence que funciona no dashboard de teste de quem escreve uma que continua funcionando quando o modelo cresce, ganha um ano fiscal diferente ou migra para DirectQuery.
Este guia mostra exatamente quando cada função entrega o mesmo resultado, quando os resultados divergem de verdade, os erros mais comuns que geram BLANK() silencioso, e o caminho de evolução — calculation groups — para quem precisa escalar essas medidas em um ambiente corporativo.
Esse artigo é para você se:
- Você já criou uma medida TOTALYTD ou SAMEPERIODLASTYEAR e ela voltou em branco para parte das linhas, sem nenhum erro visível
- Você precisa decidir entre as três funções e não sabe qual usar em cada cenário, ou se elas dão no mesmo
- Você mantém dezenas de medidas de YTD/YoY em um modelo corporativo e sente que isso já virou um problema de manutenção
Por que essas três funções existem (e por que parecem a mesma coisa)
Toda comparação temporal no Power BI depende do mesmo princípio: pegar o contexto de filtro atual (o mês, o trimestre, o ano selecionado no visual) e trocá-lo por outro conjunto de datas — o início do ano, o mesmo período do ano passado, o mês anterior.
As funções de Time Intelligence existem para gerar esse novo conjunto de datas sem que você precise escrever a lógica de filtro na mão toda vez.
O ponto que a maioria dos tutoriais não explica é que essas funções têm uma hierarquia interna:
- TOTALYTD é, na prática, uma forma resumida de escrever
CALCULATE(<expressão>, DATESYTD(<datas>)). Não existe nada que TOTALYTD faça que essa combinação não faça — só que de forma mais explícita. Isso é confirmado pela própria documentação técnica de referência da SQLBI, o DAX GUIDE: TOTALYTD é funcionalmente equivalente a usar CALCULATE combinado com DATESYTD. - SAMEPERIODLASTYEAR corresponde, internamente, a
DATEADD(<datas>, -1, YEAR). Para comparação de um ano contra o anterior, as duas funções entregam exatamente o mesmo número — a diferença é só de legibilidade do código. - DATEADD é a função mais genérica das três: desloca um conjunto de datas para frente ou para trás por dia, mês, trimestre ou ano — SAMEPERIODLASTYEAR é apenas um caso particular dela, fixo em “-1 ano”.
Entender isso muda a forma como você decide qual usar. Não é “qual função é mais fácil de lembrar”, é “qual delas te dá o controle que a situação exige”.
Tabela de decisão rápida: qual função usar
| Situação | Função recomendada | Por quê |
|---|---|---|
| Total acumulado do início do ano até a data corrente, medida nova | CALCULATE([Medida], DATESYTD('Data'[Data])) | Equivalente a TOTALYTD, mas mais explícito e sem o parâmetro string de ano fiscal |
Você já tem TOTALYTD em uso em medidas existentes, sem ano fiscal customizado | TOTALYTD (manter) | Funciona corretamente para ano fiscal padrão; não há motivo técnico para reescrever medidas que já funcionam |
| Ano fiscal termina em data diferente de 31/dez | CALCULATE([Medida], DATESYTD('Data'[Data], "30/06")) | Documentar o parâmetro fiscal separado da fórmula reduz erro de digitação |
| Comparar o mesmo período do ano anterior (YoY simples) | CALCULATE([Medida], SAMEPERIODLASTYEAR('Data'[Data])) | Mais legível quando a intenção é sempre “um ano atrás” |
| Comparar mês anterior, trimestre anterior, ou qualquer deslocamento que não seja um ano | CALCULATE([Medida], DATEADD('Data'[Data], -1, MONTH)) | SAMEPERIODLASTYEAR não aceita outro intervalo além de ano |
| Selecionar dias parciais de um mês e querer o período completo correspondente no passado | PARALLELPERIOD | DATEADD desloca as datas selecionadas; PARALLELPERIOD sempre retorna o período inteiro |
| Modelo com dezenas de métricas precisando de YTD/PY/YoY | Calculation Group | Evita criar uma variante de cada função para cada medida base |
| Modelo grande em DirectQuery com agregações pesadas | Funções nativas (SAMEPERIODLASTYEAR/DATEADD) ou funções de janela (OFFSET) | Lógicas manuais equivalentes não recebem a mesma otimização do motor |
Dois termos da tabela merecem uma referência rápida antes de seguir: DirectQuery é o modo de conexão em que o Power BI consulta os dados direto na fonte, sem importá-los para o modelo — por isso a performance das funções de Time Intelligence importa tanto nesse cenário.
Calculation Group é um objeto do modelo que centraliza a lógica de YTD, PY e YoY em um único lugar, reaplicável a qualquer medida base — a seção de dicas avançadas mais adiante mostra como criar um na prática.
Aplicação prática: construindo e comparando as medidas passo a passo
Imagine uma tabela de vendas de uma distribuidora de materiais de construção, com registros diários de faturamento por filial, cobrindo o período de 01/01/2024 a 31/12/2026.
É a partir dessa base — disponível para download logo abaixo — que as três medidas a seguir foram construídas.
Passo 1 — Confirme a tabela de datas
Antes de escrever qualquer fórmula, confirme que existe uma tabela calendário criada e marcada como Tabela de Datas no Power BI dedicada (não a coluna de data da tabela de vendas), contínua, sem lacunas — se ainda não tiver uma, vale montar essa base antes de seguir com as fórmulas.
Passo 2 — Crie a medida base
Toda medida de Time Intelligence parte de uma medida base já existente, nunca de uma coluna direto da tabela de fatos.
Faturamento = SUM('Vendas'[ValorFaturado])
Passo 3 — Faturamento acumulado no ano (YTD)
A primeira medida responde a uma pergunta recorrente em qualquer fechamento: quanto a distribuidora já faturou desde o início do ano até a data corrente. É essa a lógica que o DATESYTD resolve dentro do CALCULATE.
Faturamento YTD =
CALCULATE(
[faturamento],
DATESYTD(Calendario[Date])
)

Prefira essa forma explícita a TOTALYTD([Faturamento], 'Calendário'[Data]). O resultado é idêntico, mas a versão explícita facilita adicionar um ano fiscal customizado depois, sem reescrever a medida inteira.
Passo 4 — Faturamento comparado ao mesmo período do ano anterior (PY)
A segunda medida compara o faturamento atual com o mesmo período do ano anterior — o que no vocabulário de BI costuma ser chamado de PY, sigla de Prior Year (ano anterior). É a base de qualquer análise de crescimento ano a ano.
Faturamento PY (mesmo período ano anterior) =
CALCULATE(
[faturamento],
SAMEPERIODLASTYEAR(Calendario[Date])
)

Passo 5 — Faturamento comparado ao mês anterior
A terceira medida desloca a data para o mês imediatamente anterior — o tipo de comparação que o SAMEPERIODLASTYEAR não cobre, porque ele só desloca um ano inteiro. Para isso, entra o DATEADD, a única das três funções que aceita DAY, MONTH e QUARTER como intervalo.
Faturamento Mês Anterior =
CALCULATE(
[faturamento],
DATEADD(Calendario[Date], -1, MONTH)
)

Faturamento do mês vs. mês anterior (DATEADD), recorte de março a dezembro de 2025. A linha laranja mostra a variação percentual entre os dois — como em jun/2025, com queda de -13% em relação a maio.
Erros comuns
Erro 1: DATEADD retorna BLANK() para parte das linhas
O que acontece: a medida de mês anterior ou ano anterior funciona para a maior parte dos períodos, mas fica em branco silenciosamente em alguns meses ou no início da série histórica.
Causa raiz: DATEADD só retorna datas que já existem fisicamente na coluna de datas de origem — se a tabela de calendário tem lacunas, não é contínua, ou não cobre o ano anterior completo, a função não gera erro: ela simplesmente devolve BLANK() para essas linhas, o que passa despercebido em um relatório sem revisão cuidadosa.
Solução: gerar a tabela de calendário com CALENDAR ou CALENDARAUTO, garantindo que ela cubra do primeiro ao último dia de anos completos, incluindo o ano anterior ao início dos dados de venda, se comparações históricas forem necessárias.
Erro 2: TOTALYTD “some” quando não há vendas até a data corrente no ano
O que acontece: a medida YTD aparece em branco ou com valor inconsistente quando o contexto avalia uma data futura em relação aos dados carregados, ou quando o filtro de ano corrente não tem nenhum registro até aquele ponto.
Causa raiz: uso de TOTALYTD sem considerar que o contexto de filtro pode estar avaliando uma linha da tabela de datas sem nenhum dado correspondente na tabela de fatos — comum em matrizes que mostram todos os meses do calendário, mesmo os que ainda não aconteceram.
Solução: substituir por CALCULATE + DATESYTD combinando com uma variável de controle, ou tratar explicitamente o filtro:
Faturamento YTD (tratado) =
VAR DataMax = MAX('Calendário'[Data])
RETURN
IF(
DataMax <= TODAY(),
CALCULATE([Faturamento], DATESYTD('Calendário'[Data]))
)
A variável DataMax verifica qual é a última data existente na tabela de calendário. O IF só calcula o YTD quando essa data ainda não passou da data de hoje (TODAY()) — ou seja, a medida evita tentar acumular um período que ainda não tem dados carregados, em vez de tentar calcular e retornar algo sem sentido.
Erro 3: mensagem “uma tabela de múltiplos valores foi fornecida” ao usar DATEADD
O que acontece: o Power BI retorna um erro semântico ao tentar calcular a medida, em vez de simplesmente devolver um valor errado.
Causa raiz: a fórmula referencia a coluna de data da tabela de fatos (ex.: 'Vendas'[DataVenda]) em vez da coluna da tabela de datas marcada, ou o DATEADD está sendo usado fora de um CALCULATE/CALCULATETABLE.
Solução: sempre referenciar a coluna de data da tabela de calendário marcada como tabela de datas, dentro de CALCULATE:
// Errado
Medida Errada = DATEADD('Vendas'[DataVenda], -1, YEAR)
// Correto
Medida Correta =
CALCULATE(
[Faturamento],
DATEADD('Calendário'[Data], -1, YEAR)
)
Erro 4: resultado diferente entre DATEADD e PARALLELPERIOD para “o mesmo” período
O que acontece: duas medidas aparentemente equivalentes retornam números diferentes quando a seleção do usuário é parcial (ex.: só os primeiros 15 dias de um mês em andamento).
Causa raiz: DATEADD desloca exatamente as datas selecionadas — se o usuário filtrou 15 dias, o resultado também cobre 15 dias no período anterior. PARALLELPERIOD sempre retorna o período completo, independentemente de quantos dias foram selecionados no contexto atual.
Solução: usar DATEADD quando a intenção é respeitar exatamente o recorte do usuário; usar PARALLELPERIOD quando a intenção é sempre comparar meses, trimestres ou anos fechados, mesmo que o período atual esteja parcial (útil para “mês em curso” vs “mês fechado anterior”).
Dicas avançadas
1. Pare de criar uma medida YTD/PY/YoY para cada métrica — use Calculation Groups
Em modelos com múltiplas métricas (faturamento, custo, margem, unidades vendidas), criar uma variante de Time Intelligence para cada uma gera dezenas de medidas repetidas. Um Calculation Group resolve isso com um único conjunto de itens de cálculo reaplicável a qualquer medida base — uma prática que reduz entre 60% e 80% do total de medidas em modelos com múltiplas variantes de período.
YTD = CALCULATE(SELECTEDMEASURE(), DATESYTD('Calendário'[Data])) + 0
PY = CALCULATE(SELECTEDMEASURE(), SAMEPERIODLASTYEAR('Calendário'[Data]))
MoM =
VAR _AtualMTD = CALCULATE(SELECTEDMEASURE(), DATESMTD('Calendário'[Data]))
VAR _AnteriorMTD = CALCULATE(SELECTEDMEASURE(), DATEADD('Calendário'[Data], -1, MONTH))
RETURN _AtualMTD - _AnteriorMTD
Desde o final de 2025, o Power BI Desktop permite criar e editar calculation groups diretamente pelo Model Explorer, sem depender do Tabular Editor via XMLA endpoints — o que reduz bastante a barreira de entrada para equipes que não tinham acesso a ferramentas externas.
2. Em DirectQuery, evite lógica manual que imita SAMEPERIODLASTYEAR ou DATEADD
Se o modelo está em DirectQuery, priorize as funções nativas em vez de recriar o mesmo resultado com DATESBETWEEN ou filtros manuais equivalentes.
O motor consegue agrupar os dados na granularidade exigida pela consulta quando usa SAMEPERIODLASTYEAR ou DATEADD, reduzindo o volume de dados trafegado entre o banco e o formula engine — uma otimização que lógicas manuais não recebem, forçando o retorno de dados no nível de dia.
Em modelos muito grandes com agregações pesadas, vale avaliar também funções de janela (OFFSET) como alternativa de melhor desempenho.
Para times que ainda não migraram, essa é uma boa oportunidade de revisar medidas antigas: se alguma comparação temporal foi implementada “na unha” com FILTER e DATESBETWEEN, ela é uma candidata natural a ser reescrita com as funções nativas antes de qualquer diagnóstico de performance mais profundo.
Conclusão
TOTALYTD, SAMEPERIODLASTYEAR e DATEADD não são três formas aleatórias de fazer a mesma coisa: são uma hierarquia, e escolher a certa depende do tipo de deslocamento que a situação exige e da escala do modelo.
Dominar essa relação evita o BLANK() silencioso, elimina resultados que batem errado no fechamento e prepara suas medidas para crescer sem virar um emaranhado de fórmulas repetidas.
A partir daqui, você já sabe escolher a função certa para cada cenário sem tentativa e erro, reconhece a causa raiz dos erros mais comuns antes que eles cheguem ao dashboard, e sabe validar se uma medida está pronta para um modelo maior ou em DirectQuery.
O próximo passo natural, quando as medidas de YTD, PY e YoY começam a se multiplicar para cada métrica do modelo, é parar de criar uma variante para cada uma e centralizar essa lógica em um único lugar — os Calculation Groups.
Sobre o Autor
0 Comentários