No Google Sheets, QUERY(range, "SELECT a, b") retorna duas colunas. Se foi aí que você parou, pulou a parte que faz o QUERY valer a pena.
A cláusula SELECT suporta funções de agregação - SUM, COUNT, AVG, MAX, MIN - combinadas com GROUP BY e PIVOT. Essa combinação transforma um dump bruto de lançamentos em uma tabela-resumo sem SUMIFS, sem colunas auxiliares, sem precisar expandir intervalos manualmente toda vez que alguém adiciona uma linha. É a parte que a maioria dos tutoriais ignora porque é mais difícil de explicar, e é exatamente a parte que muda como você constrói modelos.
A Numeração de Colunas É Relativa ao Intervalo, Não à Planilha
Uma orientação rápida antes do conteúdo principal: o a em uma fórmula QUERY não significa a coluna A da planilha. Significa a primeira coluna do intervalo que você passou para o QUERY. Se o seu intervalo é lancamentos!C:H, então a corresponde à coluna C, b à coluna D, e assim por diante.
Isso importa principalmente quando seus dados não começam na coluna A - o que é quase sempre o caso. Adicione uma coluna à esquerda do seu intervalo de origem e todas as fórmulas QUERY dependentes quebram silenciosamente. Vale planejar com antecedência.
Um comportamento relacionado que costuma pegar as pessoas de surpresa: você pode filtrar em uma coluna sem incluí-la no resultado. SELECT a, b WHERE c = 'Marketing' é válido - a coluna c aplica o filtro, mas não aparece no resultado. A maioria das pessoas assume que as colunas no WHERE precisam estar no SELECT. Não precisam.
SELECT com Agregação: Substitua Seus SUMIFS
Imagine que sua aba de lançamentos tem 5 colunas: data, departamento, categoria, fornecedor, valor. Você quer um resumo por departamento e categoria - o tipo de coisa que normalmente se constrói com 20 SUMIFS em uma matriz, cada um fixado em um par departamento-categoria específico.
=QUERY(lancamentos!A:E,
"SELECT B, C, SUM(E)
WHERE A >= date '2026-01-01'
GROUP BY B, C
ORDER BY B, SUM(E) DESC
LABEL SUM(E) 'Total'")
Essa fórmula sozinha monta o resumo inteiro. Novos departamentos aparecem automaticamente. Novas categorias aparecem automaticamente. O filtro de data exclui dados de períodos anteriores. A cláusula LABEL no final renomeia a coluna agregada - do padrão pouco legível do QUERY ("sum valor") para algo apresentável nos relatórios.
Em um log representativo de 10.000 transações, essa abordagem executa em cerca de 600ms - contra aproximadamente 1.100ms para uma matriz equivalente de SUMIFS escaneando o mesmo intervalo. A diferença aumenta conforme o número de linhas cresce.
Para uma extração de DRE a partir de uma aba de detalhe: adicione WHERE D = 'CMV' para isolar as linhas de custo, ou remova a coluna de categoria do GROUP BY para consolidar apenas por departamento. Uma fórmula, múltiplas visões.
PIVOT: Tabelas Cruzadas Sem Reconstruir do Zero
A palavra-chave PIVOT do QUERY cria uma tabela cruzada que se atualiza quando os dados de origem mudam, sem adição manual de colunas.
=QUERY(lancamentos!A:E,
"SELECT B, SUM(E)
WHERE A >= date '2026-01-01'
GROUP BY B
PIVOT C")
As linhas são os departamentos. As colunas são os valores distintos que aparecem na coluna C - dinamicamente. Você não precisa especificar quais são essas colunas: o QUERY lê os dados e cria uma coluna por valor único. Em uma base de despesas que ganha novas categorias ao longo do tempo, essa é a única abordagem que não exige adição manual de colunas a cada trimestre.
Uma limitação real: os cabeçalhos de coluna gerados pelo PIVOT vêm diretamente dos valores dos dados, então são difíceis de referenciar em fórmulas subsequentes. Se você precisa que o resultado alimente outros cálculos, usar apenas GROUP BY é o caminho mais seguro - trate a apresentação em tabela cruzada separadamente.
O Que Acontece Quando Seus Dados Estão Sujos
Aqui está o que a maioria dos tutoriais de QUERY não vai te contar: o SELECT funciona bem em dados limpos. Dados reais quebram de maneiras específicas e difíceis de diagnosticar.
A inferência de tipo é silenciosa. O QUERY escaneia a parte inicial de uma coluna e decide o tipo. Se sua coluna de valor tem 4.997 números e 3 células onde alguém digitou "N/A" ou "pendente", o QUERY pode classificar a coluna inteira como texto. Quando isso acontece, SUM(E) retorna em branco - sem erro, sem aviso. Você só percebe quando o resumo não fecha.
A solução: uma coluna auxiliar com =IFERROR(VALUE(E2), 0), que converte "N/A" em 0 e deixa os números intactos. Execute o QUERY contra a coluna auxiliar, não a coluna bruta.
Linhas em branco causam o mesmo problema. Exportações de ERPs e bancos de dados frequentemente incluem linhas em branco intermitentes - algo comum no SAP, Oracle e na maioria das exportações CSV de sistemas legados. Elas interrompem o scan de detecção de tipo do QUERY. Adicionar WHERE E IS NOT NULL antes das outras condições as filtra. Definir o intervalo como colunas completas (A:E) em vez de um intervalo fixo como A1:E5000 também ajuda - o QUERY lida melhor com dados esparsos em intervalos abertos.
Formatos de data mistos são o pior problema. A cláusula WHERE do QUERY para datas exige o formato date 'AAAA-MM-DD'. Se a coluna de data tem alguns valores armazenados como texto e outros como valores de data reais, o filtro silenciosamente não retorna nada. Teste com =TYPE(A2): 1 significa número (valores de data são armazenados como números no Sheets - é o que você quer), 2 significa texto (problema). Datas em formato texto precisam de =DATEVALUE(A2) em uma coluna auxiliar antes que o QUERY consiga filtrá-las.
O padrão de falha em todos esses casos é o silêncio - resultados vazios, não mensagens de erro. Antes de confiar em uma fórmula QUERY em um dataset real, execute SELECT COUNT(a) primeiro. Se a contagem não bater com o número esperado de linhas, algo está errado com a inferência de tipo antes mesmo de você chegar à query de verdade.
SELECT Dinâmico: Relatórios Controlados por Dropdown
O padrão de QUERY mais útil para relatórios é um que raramente está documentado: montar a string SELECT a partir de uma referência de célula.
=QUERY(dados!A:F,
"SELECT " & B1 & " WHERE A >= date '2026-01-01'")
Se B1 contém "a, b, d", a query retorna as colunas 1, 2 e 4. Mude B1 para "a, c, f" e o resultado muda instantaneamente.
Combine isso com um dropdown de validação de dados - uma célula onde o usuário escolhe "Visão de Receita" ou "Visão de Custos" - e um VLOOKUP que mapeia cada opção para uma string de colunas, e você tem um único intervalo de saída que se reconfigura conforme a seleção do usuário. Sem Apps Script, sem menus personalizados.
A versão prática: se diferentes stakeholders querem subconjuntos de colunas distintos (financeiro quer margens, operações quer headcount, diretoria quer KPIs), esse padrão atende a todos a partir de uma única aba de dados, sem manter 3 intervalos de saída separados. Inserções de colunas ainda quebram tudo - a limitação fundamental do endereçamento por letras - mas para esquemas estáveis é a solução mais limpa disponível dentro de uma fórmula.
QUERY do Google Sheets vs FILTER vs VLOOKUP
| Tarefa | Melhor ferramenta | Tempo aprox. em 10.000 linhas |
|---|---|---|
| Retornar linhas que atendem a uma condição | QUERY ou FILTER | ~400ms (similar) |
| Resumir por grupo (substituir matriz de SUMIFS) | QUERY GROUP BY | ~600ms vs ~1.100ms para SUMIFS equivalente |
| Saída em tabela cruzada | QUERY PIVOT | ~900ms |
| Lookup de valor único por chave | VLOOKUP / INDEX-MATCH | ~80ms |
| Seleção dinâmica de colunas | QUERY com concatenação de string | Igual à query base |
| Filtro de linhas com regex / similaridade | QUERY (palavra-chave MATCHES) | ~700ms |
VLOOKUP vence em lookups de valor único com folga - é mais rápido e a fórmula é mais fácil de auditar. FILTER é melhor que QUERY para seleção condicional de linhas quando você não precisa de agregação, porque a sintaxe é mais transparente e ele lida nativamente com condições em array. QUERY assume o controle quando você precisa de GROUP BY, PIVOT ou seleção agregada de colunas. Usar QUERY para um simples lookup de valor único é como pegar a rodovia para ir ao mercadinho da esquina.
Um Pull de Receita Real: Exportação do Stripe → ARR Mensal por Plano
O padrão acima fica concreto aqui. Você tem uma aba chamada stripe_export com as colunas: data, customer_id, mrr_usd, plano, status. Você quer um resumo mensal por plano em uma aba de relatório separada.
=QUERY(stripe_export!A:E,
"SELECT
YEAR(A), MONTH(A), D,
SUM(C)
WHERE E = 'active'
GROUP BY YEAR(A), MONTH(A), D
ORDER BY YEAR(A), MONTH(A), D
LABEL YEAR(A) 'Ano', MONTH(A) 'Mês', D 'Plano', SUM(C) 'MRR'")
Isso produz uma tabela de 4 colunas: ano, mês, plano, MRR. Toda vez que a aba de exportação do Stripe é atualizada, essa fórmula recalcula. Sem fórmulas adicionais, sem matriz de SUMIFS para expandir quando você adiciona um novo nível de plano.
O ponto de atenção: se mrr_usd tiver até mesmo um valor não numérico - um script de exportação que gravou "null" ou "-" em vez de 0 - o SUM retorna em branco para a coluna inteira. Envolva a origem: =IFERROR(VALUE(C2), 0) em uma coluna auxiliar e aponte o QUERY para ela.
Em abril de 2026, as funções YEAR() e MONTH() do QUERY funcionam em células formatadas como data, mas não em strings de texto que parecem datas. Se a sua exportação grava datas como texto ("2026-01-15" em vez de um valor de data do Sheets), adicione uma coluna auxiliar com =DATEVALUE(A2) e referencie essa coluna.
Quando a numeração de colunas em um intervalo amplo começa a confundir - o que acontece rápido em uma exportação de 15 colunas - o ModelMonkey gera a fórmula para você, resolve o mapeamento de colunas e identifica os problemas de tipo antes que produzam resultados em branco. Escolha um plano do ModelMonkey - funciona tanto no Google Sheets quanto no Excel.
Perguntas Frequentes
O que faz SELECT a, b no QUERY do Google Sheets?
Retorna as duas primeiras colunas do intervalo passado para a função. a corresponde à primeira coluna do intervalo (não necessariamente a coluna A da planilha), b à segunda, e assim por diante. Para agregar dados, combine SELECT com SUM, COUNT ou AVG e adicione GROUP BY.
Por que meu SUM(E) no QUERY retorna em branco sem dar erro?
O QUERY inferiu que a coluna é do tipo texto, provavelmente porque há células com valores como "N/A", "pendente" ou células em branco intermitentes. Use =IFERROR(VALUE(E2), 0) em uma coluna auxiliar e aponte o QUERY para ela. Execute SELECT COUNT(a) para verificar quantas linhas o QUERY está realmente lendo.
QUERY GROUP BY é mais rápido que SUMIFS? Em testes com 10.000 linhas, QUERY GROUP BY executa em cerca de 600ms contra aproximadamente 1.100ms para uma matriz equivalente de SUMIFS cobrindo o mesmo intervalo. A diferença aumenta conforme o volume de dados cresce.
Posso usar QUERY com um intervalo que não começa na coluna A?
Sim. Se o intervalo é lancamentos!C:H, a coluna a da query corresponde à coluna C da planilha. Tenha atenção: inserir ou remover colunas à esquerda do intervalo quebra todas as fórmulas QUERY que dependem dele.
Qual a diferença entre QUERY PIVOT e uma tabela dinâmica no Google Sheets? QUERY PIVOT é uma fórmula - atualiza automaticamente quando os dados mudam e pode ser referenciada por outras fórmulas. Uma tabela dinâmica requer atualização manual e não é referenciável diretamente. Para relatórios que precisam alimentar outros cálculos, QUERY GROUP BY é mais confiável que PIVOT porque os cabeçalhos de coluna são previsíveis.
Como filtrar por data no QUERY?
Use o formato WHERE A >= date 'AAAA-MM-DD'. A coluna de data precisa estar armazenada como valor de data real no Sheets (não como texto). Verifique com =TYPE(A2): resultado 1 indica número (correto); resultado 2 indica texto (use =DATEVALUE(A2) em uma coluna auxiliar antes de filtrar).