FalaDevs – Artigos e Tutoriais de Programação | Dicas e Técnicas Avançadas

Fluxograma ilustrando a ordem de execução de uma query SQL, começando com FROM e JOINs, passando por WHERE, GROUP BY, HAVING, SELECT e terminando com ORDER BY, mostrando como os dados são filtrados em cada etapa.

Você sabia que o SELECT não é executado primeiro? Entenda a ordem real das queries SQL

Fala Devs! Beleza?

Hoje vamos desmistificar um daqueles conceitos que todo mundo que trabalha com banco de dados acha que sabe, mas que pode gerar uns bugs bem chatos se não for compreendido a fundo. Sabe aquela query SQL que você escreve bonitinha, começando com SELECT? Então… E se eu te disser que o banco de dados nem começa por ele?

Pois é! A ordem que a gente escreve uma consulta no nosso editor não é, nem de longe, a mesma ordem que o motor do banco de dados (como o nosso querido PostgreSQL) a executa. Entender essa “ordem real” não é só uma curiosidade, é uma necessidade para otimizar consultas, evitar erros e realmente dominar o SQL.

Bora mergulhar nessa lógica e entender de uma vez por todas como o banco de dados pensa?

A Ordem Escrita vs. A Ordem de Execução Real

Quando escrevemos uma query, geralmente seguimos uma estrutura padrão, quase como uma receita de bolo:

SELECT
    coluna1,
    COUNT(coluna2)
FROM
    tabela
WHERE
    condicao = TRUE
GROUP BY
    coluna1
HAVING
    COUNT(coluna2) > 10
ORDER BY
    coluna1;


Visualmente, o SELECT vem primeiro, certo? Nossa mente lê de cima para baixo. Mas o SGBD (Sistema de Gerenciamento de Banco de Dados) tem um plano de execução lógico que segue uma sequência completamente diferente. Pense nisso como o compilador do seu código: ele não lê e executa linha por linha na ordem que você escreveu, mas interpreta, otimiza e depois executa.

A ordem real de execução é pensada para ser o mais eficiente possível, filtrando os dados o quanto antes para trabalhar com um conjunto menor de informações nas etapas seguintes.

A Ordem Lógica de Execução do SQL

Então, qual é a mágica por trás do pano? O PostgreSQL e a maioria dos bancos de dados relacionais seguem uma sequência parecida com esta:

FROM e JOINs

WHERE

GROUP BY

HAVING

SELECT

ORDER BY


Vamos detalhar cada passo para ficar bem claro.

1. FROM e JOINs: A Origem dos Dados
A primeira coisa que o banco de dados faz é identificar de onde os dados virão. Ele olha para a cláusula FROM para saber a tabela principal e depois resolve todas as cláusulas JOIN para combinar os dados de múltiplas tabelas. Nesta fase, ele está montando um grande “pacote” de dados brutos, com todas as linhas e colunas das tabelas envolvidas.

2. WHERE: A Primeira Filtragem
Com o pacotão de dados montado, o próximo passo é aplicar o primeiro filtro. A cláusula WHERE entra em ação para descartar todas as linhas que não atendem às condições especificadas. É aqui que a mágica da otimização começa: quanto mais linhas você eliminar aqui, menos trabalho o banco terá nas próximas etapas.

Ponto importante: O WHERE filtra linhas antes de qualquer agrupamento. Por isso, você não pode usar funções de agregação (como COUNT(), SUM(), AVG()) aqui.

3. GROUP BY: Agrupando os Dados
Depois que os dados foram filtrados, a cláusula GROUP BY entra em cena para agrupar as linhas que têm os mesmos valores nas colunas especificadas. O resultado disso é que, em vez de várias linhas individuais, você passa a ter “grupos” de linhas.

4. HAVING: A Segunda Filtragem (Pós-Agrupamento)
Se o WHERE filtra linhas, o HAVING filtra… grupos! Essa é a principal diferença. A cláusula HAVING é aplicada depois que os dados já foram agrupados pelo GROUP BY. É por isso que aqui você pode usar funções de agregação. Por exemplo, “me traga apenas os grupos cujo total de vendas (SUM(vendas)) seja maior que 1000”.

5. SELECT: A Seleção Final das Colunas
Finalmente, chegamos nele! Só depois de toda a filtragem e agrupamento, o SELECT é processado. Ele vai olhar para o conjunto de dados final (já filtrado e agrupado) e selecionar as colunas que você pediu. É aqui também que apelidos (AS) para colunas são finalmente reconhecidos e funções como COUNT() ou SUM() são efetivamente calculadas e exibidas.

6. ORDER BY: A Cereja do Bolo
Com o resultado final praticamente pronto, a última etapa é a ordenação. A cláusula ORDER BY pega o conjunto de dados selecionado e o organiza de forma ascendente (ASC) ou descendente (DESC).


Demonstração Prática com PostgreSQL

Bora ver isso na prática! Imagine que temos duas tabelas em nosso banco de dados PostgreSQL: usuarios e pedidos.

Tabela usuarios:

idnomeestado
1AnaSP
2BrunoRJ
3CarlaSP
4DanielMG



Tabela pedidos:

idusuario_idvalorstatus
1011150.00‘pago’
102280.00‘pago’
1031200.00‘pago’
1043300.00‘pago’
105150.00‘cancelado’
1064120.00‘pago’


Agora, vamos executar a seguinte query:

SELECT
    u.estado,
    COUNT(p.id) AS total_pedidos,
    SUM(p.valor) AS faturamento_total
FROM
    usuarios AS u
JOIN
    pedidos AS p ON u.id = p.usuario_id
WHERE
    p.status = 'pago'
GROUP BY
    u.estado
HAVING
    SUM(p.valor) >= 150
ORDER BY
    faturamento_total DESC;
SQL

Como o PostgreSQL Executa essa Query?

  1. FROM e JOIN: Primeiro, ele combina usuarios com pedidos usando a condição u.id = p.usuario_id. O resultado é uma tabela temporária gigante com todos os dados combinados.
  2. WHERE: Em seguida, ele filtra essa tabela gigante, mantendo apenas as linhas onde p.status = 'pago'. O pedido de id = 105 (da Ana) é descartado aqui.
  3. GROUP BY: Agora, ele agrupa as linhas restantes pela coluna u.estado. Teremos um grupo para ‘SP’, um para ‘RJ’ e um para ‘MG’.
  4. HAVING: O próximo passo é filtrar esses grupos. A condição é SUM(p.valor) >= 150.
    • Grupo ‘RJ’ (Bruno): Soma do valor = 80.00. É descartado.
    • Grupo ‘MG’ (Daniel): Soma do valor = 120.00. É descartado.
    • Grupo ‘SP’ (Ana e Carla): Soma do valor = 150.00 + 200 + 300.00 = 650.00. É mantido.
  5. SELECT: Agora sim! Com apenas o grupo ‘SP’ restante, o SELECT é executado. Ele pega a coluna u.estado (‘SP’), calcula o COUNT(p.id) (que dá 3) e o SUM(p.valor) (que dá 650.00), aplicando os apelidos total_pedidos e faturamento_total.
  6. ORDER BY: Como só sobrou uma linha, a ordenação não fará muita diferença visual, mas se houvesse mais resultados, eles seriam ordenados pelo faturamento_total em ordem decrescente.

Resultado Final:

estadototal_pedidosfaturamento_total
SP3650.00

Viu só? Entender essa ordem evita erros comuns, como tentar usar um alias de SELECT na cláusula WHERE. Não funciona porque o WHERE é executado antes do SELECT!

Resumindo a Jornada

Para não esquecer mais, aqui vai um resumo da ordem de execução:

  • FROM/JOIN: Junta as tabelas.
  • WHERE: Filtra as linhas brutas.
  • GROUP BY: Agrupa as linhas filtradas.
  • HAVING: Filtra os grupos criados.
  • SELECT: Escolhe as colunas e calcula as funções.
  • ORDER BY: Ordena o resultado final.

Entender essa sequência é fundamental para quem trabalha com banco de dados, seja no backend com Node.js ou até mesmo analisando dados para um app em Flutter.

E aí, essa ordem de execução já te causou alguma dor de cabeça? Ou você tem alguma dica extra sobre otimização de queries? Deixa seu comentário aí embaixo!

Até a próxima! 🚀

Picture of Daniel Albuquerque

Daniel Albuquerque

Sou um desenvolvedor apaixonado por tecnologia, com foco em Node.js, TypeScript, Flutter e PostgreSQL. Criei o FalaDevs pra compartilhar experiências reais de código, boas práticas e tudo o que aprendo no dia a dia construindo aplicações modernas.

5 1 voto
Classificação do artigo
Inscrever-se
Notificar de
guest
0 Comentários
mais antigos
mais recentes Mais votado
Feedbacks embutidos
Ver todos os comentários
0
Adoraria saber sua opinião, comente.x