Operadores, modificadores, dollar-sign expansion e as funções P() e E(): o foundation que separa o desenvolvedor intermediário do sênior.
Antes de avançar para os padrões complexos, é essencial dominar a anatomia exata. Cada parte de uma expressão Set Analysis tem um papel específico - e confundi-las é a origem de 90% dos bugs.
Sum( { set_identifier < set_modifier > } expression )
^ ^ ^
| | |
Identificador Modificador Expressão
do conjunto do conjunto de aggregation
// Exemplos práticos de identificadores// Vendas totais - ignora qualquer seleção de Região, Produto, Ano Sum({1} Valor) // Vendas na seleção atual - idêntico a Sum(Valor) sem Set Analysis Sum({$} Valor) // Vendas com a seleção anterior Sum({$_1} Valor) // Vendas no estado do bookmark "BM01" (ex.: Top 10 clientes) Sum({BM01} Valor)
Atenção crítica: {1} ignora TODAS as seleções, incluindo seleções no próprio campo da expressão. {$} respeita a seleção atual. Escolher o identificador errado é o erro mais silencioso e perigoso em Set Analysis.
Os operadores de conjunto permitem combinar, subtrair, intersectar e modificar conjuntos de dados de forma precisa. São a base da álgebra de conjuntos no Qlik - e o que torna o Set Analysis genuinamente poderoso.
Combina dois conjuntos: o resultado contém todos os elementos de ambos. Equivalente ao OR lógico quando aplicado a diferentes subconjuntos do mesmo campo.
// Vendas de Eletrônicos OU Móveis (independente da seleção atual)
Sum({<Categoria={'Eletrônicos'}> + <Categoria={'Móveis'}>} Valor)
// Equivalente mais conciso para o mesmo campo:
Sum({<Categoria={'Eletrônicos', 'Móveis'}>} Valor)
// União mais poderosa: conjuntos de campos diferentes
// Seleção atual + registros de Novembro de qualquer ano
Sum({$ + <Mes={'Novembro'}>} Valor)
// Caso real: clientes na seleção atual OU clientes VIP (independente da seleção)
Count({$ + <SegmentoCliente={'VIP'}>} DISTINCT ClienteID)
Retorna o primeiro conjunto menos os elementos que também estão no segundo. Fundamental para análises de exclusão: "tudo menos X".
// Todos os registros EXCETO devoluções
Sum({1 - <Status={'Devolução'}>} Valor)
// Seleção atual EXCETO o produto 'Produto X'
Sum({$ - <Produto={'Produto X'}>} Valor)
// Caso real: receita líquida = bruta menos cancelamentos e devoluções
Sum({1 - <TipoTransacao={'Cancelamento', 'Devolução'}>} ValorBruto)
// Todos os clientes que NÃO compraram no último mês
// (usado para análise de churn)
Count({
<ClienteID=P({1}<Mes={$(=Month(Today()))}> ClienteID)>
-
<ClienteID=P({1}<Mes={$(=Month(AddMonths(Today(),-1)))}> ClienteID)>
} DISTINCT ClienteID)
Retorna apenas os elementos presentes em ambos os conjuntos simultaneamente. Equivalente ao AND lógico entre conjuntos distintos.
// Clientes que compraram Eletrônicos E que estão na seleção atual
Count({
<ClienteID=P({1}<Categoria={'Eletrônicos'}> ClienteID)>
*
$
} DISTINCT ClienteID)
// Caso real: ticket médio dos clientes que compraram
// TANTO em Q1 QUANTO em Q4 (clientes recorrentes sazonais)
Avg({
<ClienteID=P({1}<Trimestre={'Q1'}> ClienteID)>
*
<ClienteID=P({1}<Trimestre={'Q4'}> ClienteID)>
} ValorPedido)
// Operador * é a ferramenta correta para cohort analysis:
// "qual o LTV dos clientes que passaram por ambas as condições"
Retorna elementos que estão em um conjunto OU no outro, mas não em ambos. Útil para análises de comparação onde você quer destacar o que é exclusivo de cada conjunto.
// Produtos vendidos em 2023 OU em 2024, mas não em ambos
// (produtos que entraram ou saíram do portfólio)
Count({
<ProdutoID=P({1}<Ano={2023}> ProdutoID)>
/
<ProdutoID=P({1}<Ano={2024}> ProdutoID)>
} DISTINCT ProdutoID)
// Interpretação:
// Conjunto A: produtos com vendas em 2023
// Conjunto B: produtos com vendas em 2024
// A / B = produtos novos (só em 2024) + produtos descontinuados (só em 2023)
Modificadores alteram a seleção ativa de um campo específico dentro do conjunto. São expressos entre < > e determinam exatamente quais valores de cada dimensão participam do cálculo.
// Define exatamente quais valores
// o campo deve ter no conjunto
Sum({<Ano={2024}>} Valor)
Sum({<Região={'Sul', 'Sudeste'}>} Valor)
Sum({<Status={'Ativo'}>,
Ano={2024}>} Valor)
// Ignora a seleção atual do campo
// e usa os valores especificados
// Remove a seleção de um campo específico
// mantendo as seleções de outros campos
// Ignora seleção de Ano, mantém o resto
Sum({<Ano=>} Valor)
// Ignora Mês E Trimestre, mantém demais
Sum({<Mes=, Trimestre=>} Valor)
// Prático para "total do ano" dentro
// de um contexto filtrado por semana
O modificador mais poderoso: o conjunto de valores é determinado por uma expressão avaliada em tempo de renderização. Combina Set Analysis com lógica dinâmica.
// Ano atual derivado de expressão - dinâmico, nunca precisa ser atualizado
Sum({<Ano={$(=Year(Today()))}>} Valor)
// Mês anterior calculado dinamicamente
Sum({<Mes={$(=Month(AddMonths(Today(), -1)))},
Ano={$(=Year(AddMonths(Today(), -1)))}>} Valor)
// Top N valores do campo Produto (definido por variável vN)
// $(vN) expande para o valor da variável em tempo de cálculo
Sum({<ProdutoID=Top(Rank(Sum(Valor)), 1, $(vN))>} Valor)
// Período dinâmico: do início do ano até hoje
Sum({<Data={">=$(=YearStart(Today()))<=$(=Today())"}>} Valor)
A diferença entre Ano={2024} e Ano={$(=Year(Today()))} parece pequena, mas é crítica em produção. O segundo sempre calcula o ano correto - sem precisar atualizar a expressão a cada virada de ano.
// Produtos cujo nome começa com "Pro"
Sum({<Produto={"Pro*"}>} Valor)
// Clientes cujo e-mail é do domínio @empresa.com
Count({<Email={"*@empresa.com"}>} DISTINCT ClienteID)
// Registros com código que contém "BR" em qualquer posição
Sum({<CodigoPais={"*BR*"}>} Valor)
// Combinando wildcard com expressão:
// Produtos que começam com a letra selecionada pelo usuário
// (vLetra é uma variável definida por um input box)
Sum({<Produto={"$(vLetra)*"}>} Valor)
A dollar-sign expansion $( ) é o mecanismo que torna o Set Analysis verdadeiramente dinâmico. Ela resolve o conteúdo da expansão antes que o Set Analysis seja avaliado - permitindo que variáveis, expressões e até mesmo outras expressões Set Analysis definam os parâmetros do conjunto.
// Padrão 1: variável como filtro dinâmico// Script: SET vAnoAtual = Year(Today()); // Na expressão: Sum({<Ano={$(vAnoAtual)}>} Valor) // Expande para: Sum({<Ano={2025}>} Valor) // Atualiza automaticamente a cada reload sem alterar expressões // Padrão 2: expressão dinâmica como parâmetro // Período: do primeiro dia do mês até hoje Sum({<Data={">=$(=MonthStart(Today()))<=$(=Today())"}>} Valor) // Padrão 3: variável contendo uma expressão Set Analysis completa // Script: SET vFiltroVIP = '{<SegmentoCliente={''VIP''}>}'; // Na expressão: Sum($(vFiltroVIP) Valor) // Expande para: Sum({<SegmentoCliente={'VIP'}>} Valor) // Reuso do filtro em múltiplos gráficos sem repetição
// Padrão 4: expansão numérica para evitar problemas de locale// Variável: LET vMeta = 150000.50; // Problema: em locales com vírgula como decimal, // $(vMeta) pode expandir para "150.000,50" - inválido no Set Analysis // Errado (pode quebrar em locales diferentes): Sum({<Valor={>$(vMeta)}>} Pedidos) // Correto - $(#vMeta) retorna sempre o número sem formatação: Sum({<Valor={>$(#vMeta)}>} Pedidos) // Sempre expande para: Sum({<Valor={>150000.5}>} Pedidos)
Regra prática: sempre que o valor do modificador vier de uma variável numérica, use $(#variavel) ao invés de $(variavel). Evita bugs silenciosos em ambientes com configuração regional diferente do ambiente de desenvolvimento.
As funções P() (Possible Values) e E() (Excluded Values) são as ferramentas mais sofisticadas do Set Analysis. Permitem usar conjuntos de valores possíveis ou excluídos de um campo como parâmetro de outro campo - criando filtros cruzados de alta precisão.
// P(campo) retorna o conjunto de valores
// POSSÍVEIS (não excluídos) de um campo
// na seleção atual ou em um conjunto definido
// Clientes que compraram na seleção atual
P(ClienteID)
// Produtos possíveis no conjunto {1} filtrado por Categoria
P({1}<Categoria={'Eletrônicos'}> ProdutoID)
// Uso: filtrar OUTRO campo pelos valores possíveis deste
Sum({<ClienteID=P({1}<Regiao={'Sul'}> ClienteID)>} Valor)
// "Vendas de clientes que são da região Sul"
// E(campo) retorna o conjunto de valores
// EXCLUÍDOS (cinza no Qlik) de um campo
// na seleção atual
// Clientes excluídos pela seleção atual
E(ClienteID)
// Uso: calcular sobre o que foi excluído
// (análise de "o que ficou de fora")
Sum({<ClienteID=E(ClienteID)>} Valor)
// "Vendas dos clientes que foram excluídos
// pela seleção atual" - análise de impacto
O uso mais poderoso de P() é o filtro cruzado entre campos relacionados. Em vez de listar valores explícitos, você instrui o Qlik a "usar os valores do campo X que satisfazem a condição Y como filtro para o campo Z".
// Caso 1: vendas geradas por clientes que compraram um produto específico
// Sem P(): impossível sem JOIN no script
// Com P(): elegante e direto
Sum({
<ClienteID = P({1}<ProdutoID={'PROD-LAPTOP-001'}> ClienteID)>
} Valor)
// Passo a passo:
// 1. P({1}<ProdutoID={'PROD-LAPTOP-001'}> ClienteID)
// → retorna todos os ClienteIDs que compraram PROD-LAPTOP-001
// 2. <ClienteID = [esse conjunto de IDs]>
// → filtra os dados para esses clientes
// 3. Sum(Valor) sobre esses dados filtrados
// Caso 2: análise de cross-sell
// Quanto os compradores de A também gastam em outras categorias?
Sum({
<ClienteID = P({1}<Categoria={'Eletrônicos'}> ClienteID),
Categoria = {'Eletrodomésticos'}>
} Valor)
// "Vendas na categoria Eletrodomésticos
// feitas por clientes que também compraram Eletrônicos"
// Caso 3: hierarquia - vendas de gerentes cujos liderados atingiram a meta
Sum({
<GerenteID = P({1}<PercentualMeta={>100}> GerenteID)>
} ValorBonificacao)
// Cohort intersection: clientes que compraram em AMBOS os períodos
// (clientes de alta retenção - compraram Q1 E Q3)
Count({
<ClienteID =
P({1}<Trimestre={'Q1'}> ClienteID)
*
P({1}<Trimestre={'Q3'}> ClienteID)
>
} DISTINCT ClienteID)
// Cohort difference: novos clientes no período atual
// (compraram agora, mas NÃO compraram no período anterior)
Sum({
<ClienteID =
P({1}<Ano={$(=Year(Today()))}> ClienteID)
-
P({1}<Ano={$(=Year(Today())-1)}> ClienteID)
>
} Valor)
// "Receita gerada por clientes que compraram pela primeira vez este ano"
P() e E() são avaliadas no contexto do conjunto que as envolve. P({1} Campo) e P({$} Campo) são resultados completamente diferentes: o primeiro ignora a seleção, o segundo a respeita. Sempre seja explícito sobre qual contexto você quer.