| name | data-write-query |
| description | Escreve SQL otimizado para o stack Evolution (PostgreSQL primário) com boas práticas. Use quando precisar traduzir uma necessidade de dados em SQL, construir uma query com múltiplas CTEs, joins e agregações, otimizar uma query contra tabelas grandes, ou obter sintaxe específica para consultas no banco do Evo CRM, Evo AI, ou qualquer serviço do stack Evolution. Dialetos secundários disponíveis: Snowflake, BigQuery, MySQL, DuckDB. |
data-write-query — Escrever SQL Otimizado
Escreve uma query SQL a partir de uma descrição em linguagem natural, otimizada para o dialeto PostgreSQL (stack padrão Evolution) e seguindo boas práticas.
Uso
/data-write-query <descrição do que você precisa consultar>
Fluxo de Trabalho
1. Entender a Requisição
Analisar a descrição do usuário para identificar:
- Colunas de saída: Quais campos devem estar no resultado?
- Filtros: Quais condições limitam os dados (intervalos de tempo, segmentos, status)?
- Agregações: Há operações GROUP BY, contagens, somas, médias?
- Joins: É necessário combinar múltiplas tabelas?
- Ordenação: Como os resultados devem ser classificados?
- Limites: Há um requisito de top-N ou amostragem?
2. Determinar o Dialeto SQL
Dialeto primário do workspace:
- PostgreSQL — padrão para todo o stack Evolution (Evo CRM, Evo AI, serviços internos, Aurora RDS, Supabase, Neon)
Dialetos secundários (se explicitamente solicitados):
- Snowflake
- BigQuery (Google Cloud)
- Redshift (Amazon)
- Databricks SQL
- MySQL / Aurora MySQL
- DuckDB
- SQLite
Se o usuário não especificar, assumir PostgreSQL como padrão.
3. Descobrir o Schema (Se Conectado)
Se a fonte de dados estiver disponível via MCP ou CLI:
- Buscar tabelas relevantes com base na descrição do usuário
- Inspecionar nomes de colunas, tipos e relacionamentos
- Verificar índices, particionamento ou clustering que afetam a performance
- Procurar views ou views materializadas que possam simplificar a query
Queries de exploração de schema (PostgreSQL):
SELECT table_name, table_type
FROM information_schema.tables
WHERE table_schema = 'public'
ORDER BY table_name;
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_name = 'nome_da_tabela'
ORDER BY ordinal_position;
SELECT relname AS tabela,
pg_size_pretty(pg_total_relation_size(relid)) AS tamanho_total
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC;
SELECT indexname, indexdef
FROM pg_indexes
WHERE tablename = 'nome_da_tabela';
4. Escrever a Query
Seguir estas boas práticas:
Estrutura:
- Usar CTEs (cláusulas WITH) para legibilidade quando queries têm múltiplos passos lógicos
- Uma CTE por transformação lógica ou fonte de dados
- Nomear CTEs de forma descritiva (ex:
novos_clientes_diarios, usuarios_ativos, receita_por_plano)
Performance:
- Nunca usar
SELECT * em queries de produção — especificar apenas as colunas necessárias
- Filtrar cedo (push de cláusulas WHERE o mais próximo possível das tabelas base)
- Usar filtros de partição quando disponíveis (especialmente partições de data)
- Preferir
EXISTS sobre IN para subconsultas com grandes conjuntos de resultados
- Usar os tipos corretos de JOIN (não usar LEFT JOIN quando INNER JOIN é o correto)
- Evitar subconsultas correlacionadas quando um JOIN ou window function funciona
- Atenção a joins explosivos (many-to-many)
Legibilidade:
- Adicionar comentários explicando o "porquê" para lógica não óbvia
- Usar indentação e formatação consistentes
- Criar aliases de tabelas com nomes abreviados significativos (não apenas
a, b, c)
- Colocar cada cláusula principal em sua própria linha
Otimizações específicas do PostgreSQL:
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT ...;
SELECT * FROM tabela
ORDER BY criado_em DESC
LIMIT 50 OFFSET 0;
SELECT
cliente_id,
valor,
SUM(valor) OVER (PARTITION BY cliente_id ORDER BY data_pagamento) AS valor_acumulado,
ROW_NUMBER() OVER (PARTITION BY cliente_id ORDER BY data_pagamento DESC) AS rn
FROM pagamentos;
SELECT DISTINCT ON (cliente_id)
cliente_id, plano, criado_em
FROM assinaturas
ORDER BY cliente_id, criado_em DESC;
DATE_TRUNC('month', criado_em)
EXTRACT(DOW FROM criado_em)
NOW() AT TIME ZONE 'America/Sao_Paulo'
criado_em ZONE ZONE
DATE_PART(, fim inicio)
dados
dados
jsonb_array_elements(dados)
dados @ ::jsonb
([, ])
(campo data)
(tags)
Padrões de query para as fontes do workspace:
WITH receita_mensal AS (
SELECT
DATE_TRUNC('month', data_pagamento) AS mes,
SUM(valor_cents) / 100.0 AS receita_total,
COUNT(DISTINCT cliente_id) AS clientes_pagantes
FROM pagamentos
WHERE status = 'succeeded'
AND data_pagamento >= NOW() - INTERVAL '12 months'
GROUP BY 1
),
crescimento AS (
SELECT
mes,
receita_total,
clientes_pagantes,
LAG(receita_total) OVER (ORDER BY mes) AS receita_anterior,
ROUND(
(receita_total - LAG(receita_total) OVER (ORDER BY mes)) /
NULLIF(LAG(receita_total) OVER (ORDER BY mes), 0) * 100, 2
) AS crescimento_pct
FROM receita_mensal
)
SELECT crescimento mes;
instancias_ativas (
instancia_id,
versao,
pais,
criado_em,
ultimo_ping
instancias
ultimo_ping NOW()
status
),
por_versao (
versao,
() total,
( pais) paises_distintos
instancias_ativas
)
versao,
total,
paises_distintos,
ROUND(total (total) (), ) percentual
por_versao
total ;
funil (
DATE_TRUNC(, criado_em) semana,
() ( etapa ) leads,
() ( etapa ) qualificados,
() ( etapa ) propostas,
() ( etapa ) fechados
oportunidades
criado_em NOW()
)
semana,
leads,
qualificados,
propostas,
fechados,
ROUND(qualificados (leads, ), ) taxa_qualificacao,
ROUND(fechados (leads, ), ) taxa_fechamento
funil
semana;
cohorts (
cliente_id,
DATE_TRUNC(, primeira_assinatura) cohort_mes
clientes
),
atividade_mensal (
cliente_id,
DATE_TRUNC(, data_evento) mes_ativo
eventos
),
retencao (
c.cohort_mes,
DATE_PART(, AGE(a.mes_ativo, c.cohort_mes)) meses_depois,
( c.cliente_id) clientes_retidos
cohorts c
atividade_mensal a (cliente_id)
a.mes_ativo c.cohort_mes
,
),
tamanho_cohort (
cohort_mes, ( cliente_id) tamanho
cohorts
)
r.cohort_mes,
r.meses_depois,
r.clientes_retidos,
tc.tamanho tamanho_cohort,
ROUND(r.clientes_retidos tc.tamanho, ) taxa_retencao
retencao r
tamanho_cohort tc (cohort_mes)
r.cohort_mes, r.meses_depois;
5. Apresentar a Query
Fornecer:
- A query completa em bloco de código SQL com syntax highlighting
- Breve explicação do que cada CTE ou seção faz
- Notas de performance se relevantes (uso de índice, bottlenecks potenciais, custo esperado)
- Sugestões de modificação — como ajustar para variações comuns (intervalo de tempo diferente, granularidade diferente, filtros adicionais)
6. Oferecer Execução
Se a fonte de dados estiver disponível via skill, oferecer executar a query e analisar os resultados. Se o usuário preferir executar manualmente, a query está pronta para copiar e colar.
Exemplos
Agregação simples:
/data-write-query Contagem de assinaturas por plano nos últimos 30 dias
Análise complexa:
/data-write-query Análise de retenção por cohort — agrupar clientes pelo mês de assinatura, depois mostrar qual percentual ainda está ativo aos 1, 3, 6 e 12 meses
Performance crítica:
/data-write-query Temos uma tabela de eventos com 500M de linhas particionada por data. Encontrar os 100 usuários com mais eventos nos últimos 7 dias com o tipo de evento mais recente de cada um.
Com timezone:
/data-write-query Instâncias criadas esta semana, agrupadas por dia em BRT (America/Sao_Paulo)
Dicas
- Mencionar o dialeto SQL upfront para obter a sintaxe correta imediatamente (PostgreSQL é o padrão)
- Se souber os nomes das tabelas, inclua-os — caso contrário, ajudaremos a encontrá-los
- Especificar se a query precisa ser idempotente (segura para re-executar) ou é para uso único
- Para queries recorrentes, mencionar se deve ser parametrizada para intervalos de datas
- Sempre especificar o fuso horário: o stack Evolution usa UTC no banco, BRT (America/Sao_Paulo) na exibição
- Mencionar se precisa de EXPLAIN ANALYZE para diagnóstico de performance