O Custo da Query Ilegível
Em uma consultoria de dados para uma grande rede de atacarejo, encontramos um repositório de queries SQL que ninguém na equipe atual conseguia explicar completamente. Eram 47 queries de relatório, produzidas por ao menos 5 analistas diferentes ao longo de 3 anos, sem padronização de formatação, sem comentários, sem documentação de propósito.
Algumas usavam keywords em minúsculas, outras em maiúsculas. Algumas indentavam com 2 espaços, outras com tab, outras não indentavam. Aliases de tabela eram letras únicas (a, b, c) sem relação com o nome da tabela — a.valor_total em uma join de 4 tabelas era indecifrável sem rastrear de onde a vinha. Subconsultas eram aninhadas em sequência sem breaks de linha.
O problema real: toda vez que um relatório precisava ser modificado para uma nova campanha ou período, o analista responsável passava entre 45 minutos e 3 horas apenas entendendo a query existente antes de poder alterá-la. Considerando que a equipe rodava entre 8 e 15 relatórios de campanha por semana, o tempo desperdiçado em interpretação de código ilegível era considerável — e o risco de erro na modificação era alto.
Padrão de Formatação SQL para Legibilidade
O padrão que implantamos, inspirado nas convenções do SQL Style Guide de Simon Holywell e adaptado para o contexto de dados de varejo:
-- Relatório: Conversão por Canal — Campanha Black Friday 2024
-- Criado por: Equipe Analytics | Atualizado: 2024-11-30
-- Propósito: Performance de aquisição por canal de mídia paga
SELECT
sessao.utm_source AS canal,
sessao.utm_medium AS medio,
sessao.utm_campaign AS campanha,
COUNT(DISTINCT sessao.id) AS total_sessoes,
COUNT(DISTINCT pedido.id) AS total_pedidos,
SUM(pedido.valor_total) AS receita_total,
ROUND(
COUNT(DISTINCT pedido.id) * 100.0 /
NULLIF(COUNT(DISTINCT sessao.id), 0),
2
) AS taxa_conversao_pct
FROM sessoes AS sessao
LEFT JOIN pedidos AS pedido
ON pedido.sessao_id = sessao.id
AND pedido.status NOT IN ('cancelado', 'estornado')
WHERE
sessao.data_hora >= '2024-11-28 00:00:00'
AND sessao.data_hora < '2024-12-02 00:00:00'
AND sessao.utm_campaign LIKE 'black-friday%'
GROUP BY
sessao.utm_source,
sessao.utm_medium,
sessao.utm_campaign
ORDER BY
receita_total DESC;
As regras fundamentais do padrão: keywords SQL em maiúsculas, aliases descritivos (o nome da tabela, não uma letra), alinhamento de AS nas colunas do SELECT para facilitar leitura vertical, comentário de cabeçalho com propósito e autor, cada cláusula em linha própria.
Queries Essenciais para Marketing de Varejo
Conversão por Canal de Aquisição
A query acima é o ponto de partida. Para campanhas de varejo de alto volume, adicione a coluna de ROAS (Return on Ad Spend) quando a tabela de custos de mídia estiver disponível:
ROUND(
SUM(pedido.valor_total) / NULLIF(SUM(custo.valor_investido), 0),
2
) AS roas
LTV de Cliente por Segmento
-- LTV médio por segmento de cliente — últimos 12 meses
SELECT
cliente.segmento,
COUNT(DISTINCT cliente.id) AS total_clientes,
COUNT(DISTINCT pedido.id) AS total_pedidos,
ROUND(AVG(pedido.valor_total), 2) AS ticket_medio,
ROUND(SUM(pedido.valor_total)
/ COUNT(DISTINCT cliente.id), 2) AS ltv_medio_12m,
ROUND(COUNT(DISTINCT pedido.id) * 1.0
/ COUNT(DISTINCT cliente.id), 1) AS frequencia_compra
FROM clientes AS cliente
INNER JOIN pedidos AS pedido
ON pedido.cliente_id = cliente.id
AND pedido.status = 'entregue'
AND pedido.data_pedido >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH)
GROUP BY
cliente.segmento
ORDER BY
ltv_medio_12m DESC;
Performance por Categoria de Produto em Campanhas
-- Quais categorias convertem melhor em cada canal de campanha
SELECT
campanha.utm_source AS canal,
produto.categoria_nivel_1 AS categoria,
COUNT(DISTINCT item.id) AS itens_vendidos,
SUM(item.quantidade) AS unidades_totais,
SUM(item.valor_total) AS receita_categoria,
ROUND(
SUM(item.valor_total) * 100.0 /
SUM(SUM(item.valor_total)) OVER (PARTITION BY campanha.utm_source),
1
) AS pct_receita_no_canal
FROM sessoes AS campanha
INNER JOIN pedidos AS pedido
ON pedido.sessao_id = campanha.id
AND pedido.status NOT IN ('cancelado', 'estornado')
INNER JOIN itens_pedido AS item
ON item.pedido_id = pedido.id
INNER JOIN produtos AS produto
ON produto.id = item.produto_id
WHERE
campanha.data_hora >= '2024-11-28'
AND campanha.utm_campaign LIKE 'black-friday%'
GROUP BY
campanha.utm_source,
produto.categoria_nivel_1
ORDER BY
canal, receita_categoria DESC;
Por Que SQL Supera Planilhas na Análise de Varejo de Alto Volume
A pergunta mais comum quando implantamos padrões SQL em equipes de marketing de varejo é: por que não usar planilhas? A resposta tem três dimensões:
Volume: Uma rede de atacarejo com 300 lojas pode gerar 50.000 a 200.000 transações por dia. Planilhas Excel têm limite de 1,04 milhão de linhas — o que representa menos de 6 dias de dados em volumes altos. SQL processa bilhões de registros sem limite prático de memória local.
Reprodutibilidade: Uma query SQL é exatamente reproduzível — executar a mesma query amanhã com os mesmos filtros produz o mesmo resultado (para dados históricos). Uma análise em planilha depende de processos manuais de atualização, cópia e filtro, com risco de erro humano a cada iteração.
Auditabilidade: Uma query SQL bem formatada documenta a lógica de negócio — quais status de pedido são excluídos, qual é o período exato, como os segmentos são definidos. Uma planilha com filtros aplicados e linhas ocultas raramente preserva essa rastreabilidade.
Documente Queries com Comentários Inline
O padrão mínimo de documentação que exigimos em todas as queries de relatório de varejo: cabeçalho com propósito, autor e data; comentário inline em joins ou filtros não-óbvios; e comentário de alerta quando há uma regra de negócio específica do cliente codificada na query.
-- ATENÇÃO: Status 'reservado' conta como venda confirmada
-- para fins de meta (alinhado com diretoria comercial em 2024-03-15)
WHERE pedido.status IN ('entregue', 'em_transito', 'reservado')
Formate Suas Queries com a Ferramenta
O SQL Formatter da Toolbox Dev Design aplica automaticamente o padrão de formatação descrito neste artigo: keywords maiúsculas, indentação consistente, um campo por linha no SELECT. Cole qualquer query — por mais comprimida que esteja — e obtenha a versão formatada e legível em segundos.
Perguntas Frequentes
Qual banco de dados é mais comum em sistemas de varejo brasileiro?
MySQL e Microsoft SQL Server dominam os ERPs de varejo no Brasil — sistemas como Totvs, Senior e Oracle Retail geralmente usam um desses como backend. PostgreSQL é comum em startups de varejo e fintechs de cashback. A sintaxe das queries de relatório é quase idêntica entre os três para as operações de análise mais comuns (SELECT, JOIN, GROUP BY, window functions). As principais diferenças aparecem em funções de data: DATE_SUB no MySQL, DATEADD no SQL Server, DATE_TRUNC no PostgreSQL.
Como evitar que uma query pesada trave o banco de dados de produção?
Nunca execute queries analíticas pesadas diretamente no banco de produção de um varejista de alto volume. As opções: 1) réplica de leitura (read replica) — a maioria dos ERPs modernos oferece; 2) data warehouse separado (Google BigQuery, Amazon Redshift, Snowflake) para análises — dados sincronizados via ETL; 3) janela de execução fora do horário de pico (madrugada). Para verificações rápidas e pontuais, adicione LIMIT na query para evitar varreduras de tabela completa acidentais.
Como calcular o LTV de cliente quando existem devoluções e cancelamentos?
A abordagem mais precisa para varejo é usar apenas pedidos com status final positivo (entregue, concluído) e deduzir o valor de devoluções processadas. Em SQL, isso se traduz em um LEFT JOIN com a tabela de devoluções e subtração dos valores correspondentes. Para redes com alta taxa de cancelamento (como e-commerce de eletrônicos no período de troca pós-feriado), o LTV calculado sem excluir cancelamentos superestima o valor real do cliente em 15% a 40%.
O SQL Formatter pode ser usado para queries de BigQuery ou DuckDB?
Sim — a formatação de SQL padrão (ANSI SQL) é compatível com BigQuery, DuckDB, Snowflake e a maioria dos dialetos modernos. O formatador aplica regras de indentação e capitalização de keywords que são válidas em todos esses ambientes. Sintaxes específicas de dialeto (como QUALIFY no BigQuery ou UNNEST em arrays) são preservadas sem modificação, apenas formatadas para legibilidade.