Pular para o conteúdo principal

CTE em SQL: Um guia completo com exemplos

Entenda como usar expressões de tabela comuns para simplificar consultas complexas e melhorar a legibilidade. Aprenda a diferença entre CTEs não recursivos e recursivos.
Actualizado 20 de nov. de 2024  · 10 min de leitura

Se você já trabalha com SQL há algum tempo, mas não usa CTEs, provavelmente se perguntará como conseguiu passar sem eles. Eu os utilizo em praticamente todos os lugares, inclusive nas declarações SELECT, INSERT, UPDATE e DELETE.

Neste artigo, abordarei os conceitos básicos, inclusive como criar um CTE. Também abordarei aspectos mais avançados, como a diferenciação entre CTEs não recursivos e recursivos, pois ambos têm uma finalidade. 

Se você não estiver familiarizado com as operações SQL, experimente nosso curso Introdução ao SQL, muito popular, para começar. O curso é bem elaborado e abrangente, e ensinará tudo o que você precisa saber para extrair dados usando consultas eficientes.

O que é um CTE SQL?

A ideia dos CTEs ficará clara quando eu mostrar exemplos. Mas, por enquanto, podemos dizer que um CTE, ou expressão de tabela comum, é um conjunto de resultados temporário e nomeado no SQL que permite que você simplifique consultas complexas, tornando-as mais fáceis de ler e manter.

Os CTEs são comumente usados quando você trabalha com várias subconsultas. Você pode reconhecê-los porque são criados com a palavra-chave WITH eComo mencionei, eles podem ser usados em declarações SELECT INSERT, e . UPDATE DELETE

Como criar um CTE SQL

Ao criar um CTE, usamos a palavra-chave WITH para iniciar a definição do CTE. A sintaxe geral de um CTE é a seguinte:

WITH cte_name (column1, column2, ...)
AS (
    -- Query that defines the CTE
    SELECT ...
    FROM ...
    WHERE ...
)
-- Main query
SELECT ...
FROM cte_name;

Onde:

  • WITH: Inicia a definição do CTE, indicando que o nome a seguir representa um conjunto de resultados temporários.

  • cte_name: O nome é atribuído ao CTE para fazer referência a ele na consulta principal.

  • Lista de colunas opcional (column1, column2, ...): Especifica os nomes das colunas para o conjunto de resultados do CTE. Isso é útil quando os nomes das colunas precisam ser ajustados.

  • Consulta que define o CTE: A consulta interna que seleciona os dados e forma o conjunto de resultados temporários.

  • Consulta principal: Faz referência ao CTE por seu nome, usando-o como uma tabela.

Vejamos o seguinte exemplo de criação de um CTE usando uma abordagem em camadas. Suponhamos que você tenha uma tabela Employees e queira criar um CTE que selecione os funcionários com salário acima de US$ 50.000.

Etapa 1: Escreva a consulta básica

Começamos escrevendo a consulta básica SELECT:

SELECT EmployeeID, FirstName, LastName, Salary
FROM Employees
WHERE Salary > 50000;

Etapa 2: Envolva a consulta usando a palavra-chave WITH para criar um CTE

Use a palavra-chave WITH para dar um nome ao CTE.

WITH HighEarningEmployees AS (
    SELECT EmployeeID, FirstName, LastName, Salary
    FROM Employees
    WHERE Salary > 50000
)

Etapa 3: Use o CTE na consulta principal

Por fim, faça referência ao CTE em uma instrução SELECT chamando o nome do CTE definido acima.

-- Define a Common Table Expression (CTE)
WITH HighEarningEmployees AS (
    SELECT EmployeeID, FirstName, LastName, Salary
    FROM Employees
    WHERE Salary > 50000
)
-- Use the CTE to select high-earning employees
SELECT EmployeeID, FirstName, LastName
FROM HighEarningEmployees;

Para resumir as etapas acima, usamos a palavra-chave WITH para definir o CTE chamado HighEarningEmployees. A consulta interna foi usada para gerar o conjunto de dados temporário. A consulta principal faz referência ao site HighEarningEmployees para exibir as colunas especificadas EmployeeID, FirstName e LastName.

Por que os CTEs do SQL são úteis

Com base no exemplo acima, você pode se perguntar por que usamos CTEs quando até mesmo consultas simples produzem os mesmos resultados. A seguir, você encontrará os motivos:

Simplificar consultas complexas

Os CTEs dividem instruções SQL complexas em partes menores e mais gerenciáveis, tornando o código mais fácil de ler, escrever e manter. 

Suponhamos que você tenha três tabelas: Orders, Customers, e Products. Queremos descobrir a receita total gerada por cada cliente que comprou em 2024. Quando escrevemos a consulta sem usar o CTE, ela parece desordenada e difícil de ler e entender.

-- Select customer names and total revenue from their orders
SELECT c.CustomerName, SUM(p.Price * o.Quantity) AS TotalRevenue
FROM Orders o
-- Join to get customer and products table
JOIN Customers c ON o.CustomerID = c.CustomerID
JOIN Products p ON o.ProductID = p.ProductID
WHERE YEAR(o.OrderDate) = 2024
GROUP BY c.CustomerName
HAVING SUM(p.Price * o.Quantity) > 1000;

Ao usar um CTE, podemos separar a lógica em um formato mais legível:

-- Define the CTE
WITH OrderDetails AS (
    SELECT o.OrderID, c.CustomerName, p.Price, o.Quantity, o.OrderDate
    FROM Orders o
    JOIN Customers c ON o.CustomerID = c.CustomerID
    JOIN Products p ON o.ProductID = p.ProductID
    WHERE YEAR(o.OrderDate) = 2024
)
--Main query
SELECT CustomerName, SUM(Price * Quantity) AS TotalRevenue
FROM OrderDetails
GROUP BY CustomerName
HAVING SUM(Price * Quantity) > 1000;

Reutilização de código

Os CTEs ajudam a evitar a duplicação, permitindo que o mesmo conjunto de resultados seja reutilizado em diferentes partes de uma consulta. Se vários cálculos ou operações forem baseados no mesmo conjunto de dados, você poderá defini-lo uma vez em um CTE e consultá-lo conforme necessário.

Suponha que precisemos calcular a média e o total de vendas de cada categoria de produto em um banco de dados de comércio eletrônico. Podemos usar um CTE para definir os cálculos uma vez e reutilizá-los em consultas subsequentes.

-- Define a CTE to calculate total and average sales for each category
WITH CategorySales AS (
    SELECT Category, SUM(SalesAmount) AS TotalSales, AVG(SalesAmount) AS AverageSales
    FROM Products
    GROUP BY Category
)
-- Select category, total sales, and average sales from the CTE
SELECT Category, TotalSales, AverageSales
FROM CategorySales
WHERE TotalSales > 5000;

Outros aplicativos

Além de simplificar as consultas e a reutilização do código, os CTEs também têm outros usos. Não tenho condições de cobrir detalhadamente todos os usos possíveis dos CTEs. Nosso curso Manipulação de dados em SQL é uma ótima opção se você quiser continuar praticando. No entanto, documentarei alguns dos outros motivos principais aqui:

  • Organização de consultas e legibilidade: Os CTEs melhoram a legibilidade do código SQL, dividindo as consultas em etapas lógicas e sequenciais. Cada etapa do processo de consulta pode ser representada por seu próprio CTE, o que facilita o acompanhamento de toda a consulta.
  • Passagem de dados hierárquicos: Os CTEs podem ajudar a navegar em relacionamentos hierárquicos, como estruturas organizacionais, relacionamentos pai-filho ou qualquer modelo de dados que envolva níveis aninhados. Os CTEs recursivos são úteis para a consulta de dados hierárquicos porque permitem que você percorra os níveis iterativamente.
  • Agregações em vários níveis: Os CTEs podem ajudar a realizar agregações em vários níveis, como o cálculo de números de vendas em diferentes granularidades (por exemplo, por mês, trimestre e ano). O uso de CTEs para separar essas etapas de agregação garante que cada nível seja calculado de forma independente e lógica.
  • Combinação de dados de várias tabelas: Vários CTEs podem ser usados para combinar dados de diferentes tabelas, tornando a etapa final de combinação mais estruturada. Essa abordagem simplifica as uniões complexas e garante que os dados de origem sejam organizados logicamente para melhorar a legibilidade.

Técnicas avançadas de SQL CTE

Os CTEs suportam técnicas avançadas de SQL, o que os torna versáteis e úteis para diferentes casos de uso. A seguir, você encontrará alguns dos aplicativos avançados dos CTEs.

Vários CTEs em uma única consulta

Você pode definir vários CTEs em uma única consulta, o que permite transformações e cálculos complexos. Esse método é útil quando um problema exige vários estágios de processamento de dados, em que cada CTE representa um estágio distinto.

Suponha que tenhamos dados de vendas em uma tabela chamada Sales e que desejemos calcular o total de vendas de cada produto, identificar produtos com vendas totais acima da média e classificar esses produtos com base em suas vendas totais.

WITH ProductSales AS (
    -- Step 1: Calculate total sales for each product
    SELECT ProductID, SUM(SalesAmount) AS TotalSales
    FROM Sales
    GROUP BY ProductID
),
AverageSales AS (
    -- Step 2: Calculate the average total sales across all products
    SELECT AVG(TotalSales) AS AverageTotalSales
    FROM ProductSales
),
HighSalesProducts AS (
    -- Step 3: Filter products with above-average total sales
    SELECT ProductID, TotalSales
    FROM ProductSales
    WHERE TotalSales > (SELECT AverageTotalSales FROM AverageSales)
)
-- Step 4: Rank the high-sales products
SELECT ProductID, TotalSales, RANK() OVER (ORDER BY TotalSales DESC) AS SalesRank
FROM HighSalesProducts;

No exemplo acima;

  • O primeiro CTE (ProductSales) calcula o total de vendas por produto.

  • O segundo CTE (AverageSales) calcula o total médio de vendas de todos os produtos.

  • O terceiro CTE (HighSalesProducts) filtra os produtos cujas vendas totais excedem a média.

  • A consulta final classifica esses produtos com base em suas vendas totais.

CTEs em instruções UPDATE, DELETE e MERGE

Quando incorporados às operações UPDATE, DELETE e MERGE, os CTEs podem simplificar as tarefas de manipulação de dados, especialmente quando você lida com filtros complexos ou dados hierárquicos.

Usando CTE com uma instrução UPDATE

Suponha que você tenha uma tabela Employees com uma coluna EmployeeSalary. Queremos dar um aumento de 10% a todos os funcionários que trabalham na empresa há mais de 5 anos.

-- Define a CTE to find employees hired more than 5 years ago
WITH LongTermEmployees AS (
    SELECT EmployeeID
    FROM Employees
    WHERE DATEDIFF(YEAR, HireDate, GETDATE()) > 5
)
-- Update salaries by 10% for long-term employees identified in the CTE
UPDATE Employees
SET EmployeeSalary = EmployeeSalary * 1.1
WHERE EmployeeID IN (SELECT EmployeeID FROM LongTermEmployees);

O CTE LongTermEmployees identifica os funcionários que trabalham há mais de cinco anos. A declaração UPDATE usa esse CTE para aumentar seletivamente os salários.

Usando CTE com uma instrução DELETE

Agora, suponha que você tenha uma tabela chamada Products e queira excluir todos os produtos que não foram vendidos nos últimos dois anos. Podemos usar um CTE para filtrar os produtos:

-- Define a CTE to identify products not sold in the last 2 years
WITH OldProducts AS (
    SELECT ProductID
    FROM Products
    -- Use DATEADD to find products with a LastSoldDate more than 2 years ago
    WHERE LastSoldDate < DATEADD(YEAR, -2, GETDATE())
)
-- Delete products identified as old from the main table
DELETE FROM Products
WHERE ProductID IN (SELECT ProductID FROM OldProducts);

O CTE OldProducts identifica os produtos que não foram vendidos nos últimos dois anos e, em seguida, a declaração DELETE usa esse CTE para remover esses produtos.

Usando CTE com uma instrução MERGE

A instrução MERGE no SQL permite atualizações, inserções ou exclusões condicionais em uma tabela de destino com base nos dados de uma tabela de origem. No exemplo a seguir, o CTE MergedInventory combina dados de inventário novos e existentes. Em seguida, a instrução MERGE atualiza as quantidades dos produtos existentes ou insere novos produtos com base nos dados do CTE.

-- CTE to merge new and existing inventory data
WITH MergedInventory AS (
    SELECT ni.ProductID, ni.Quantity AS NewQuantity, i.Quantity AS CurrentQuantity
    FROM NewInventoryData ni
    -- Use LEFT JOIN to include all new data, even if not in current inventory
    LEFT JOIN Inventory i ON ni.ProductID = i.ProductID
)
-- Merge the prepared data into the Inventory table
MERGE INTO Inventory AS i
USING MergedInventory AS mi
ON i.ProductID = mi.ProductID
-- Update existing products with new quantities
WHEN MATCHED THEN
    UPDATE SET i.Quantity = mi.NewQuantity
-- Insert new products if they don't exist in the inventory
WHEN NOT MATCHED BY TARGET THEN
    INSERT (ProductID, Quantity) VALUES (mi.ProductID, mi.NewQuantity);

Expressões de tabela comum (CTEs) recursivas

Os CTEs recursivos ajudam a realizar operações avançadas e repetidas.

Introdução aos CTEs recursivos

Os CTEs recursivos são um tipo especial de CTE que faz referência a si mesmo em sua definição, permitindo que a consulta realize operações repetidas. Isso os torna ideais para trabalhar com dados hierárquicos ou estruturados em árvore, como organogramas, estruturas de diretório ou conjuntos de produtos. O CTE recursivo processa os dados de forma iterativa, retornando os resultados passo a passo até que uma condição de encerramento seja atendida.

Membros âncora e recursivos

Um CTE recursivo consiste em duas partes principais:

  • Membro da âncora: A parte que define a consulta base que inicia a recursão.
  • Membro recursivo: A parte que faz referência ao próprio CTE, permitindo que ele execute as operações "recursivas".

Suponha que tenhamos uma tabela Employees, em que cada linha contém um EmployeeID, EmployeeName e ManagerID. Se quisermos encontrar todos os relatórios diretos e indiretos de um gerente específico, começaremos com o membro âncora que identifica o gerente de nível superior. O membro âncora começa com o funcionário com EmployeeID = 1.

O membro recursivo encontra funcionários cujo ManagerID corresponde ao EmployeeID da iteração anterior. Cada iteração recupera o próximo nível da hierarquia.

WITH EmployeeHierarchy AS (
    -- Anchor member: select the top-level manager
    SELECT EmployeeID, EmployeeName, ManagerID, 1 AS Level
    FROM Employees
    WHERE EmployeeID = 1  -- Starting with the top-level manager
    UNION ALL
    -- Recursive member: find employees who report to the current managers
    SELECT e.EmployeeID, e.EmployeeName, e.ManagerID, eh.Level + 1
    FROM Employees e
    INNER JOIN EmployeeHierarchy eh ON e.ManagerID = eh.EmployeeID
)
SELECT EmployeeID, EmployeeName, Level
FROM EmployeeHierarchy;

Problemas ou limitações potenciais dos CTEs no SQL

Compreender os recursos e as limitações dos CTEs é importante para que você escreva consultas lógicas e legíveis. Vamos examinar algumas limitações e possíveis problemas do uso de CTEs em diferentes bancos de dados.

Limitações do SQL Server e do Azure

Há algumas limitações específicas do ambiente para CTEs do SQL quando você trabalha com o SQL Server ou o Azure Synapse Analytics. Eles incluem o seguinte:

  • SQL Server: O nível máximo de recursão padrão para CTEs recursivos é 100, que pode ser modificado usando a dica OPTION (MAXRECURSION). Se esse limite for excedido sem ajuste, ocorrerá um erro. Os CTEs não podem ser aninhados diretamente uns dentro dos outros ou definidos dentro de outro CTE.

  • Azure Synapse Analytics: Os CTEs têm suporte limitado para determinadas operações SQL, como INSERT, UPDATE, DELETE e MERGE. Além disso, os CTEs recursivos não são compatíveis com os ambientes baseados na nuvem do Azure Synapse Analytics, o que restringe a capacidade de executar determinadas operações de dados hierárquicos.

Se você estiver trabalhando com o SQL Server, saiba que a DataCamp tem muitos recursos excelentes para ajudar. Para começar, recomendo que você faça o curso Introdução ao SQL Server da DataCamp para dominar os conceitos básicos do SQL Server para análise de dados. Você pode experimentar nosso curso de carreira de Desenvolvedor do SQL Server, que abrange tudo, desde transações e tratamento de erros até análise de séries temporais. Em nosso curso de Consultas hierárquicas e recursivas no SQL Server, você aprenderá a escrever consultas avançadas no SQL Server, incluindo métodos que envolvem CTEs.

Outros possíveis problemas

Embora os CTEs sejam úteis para simplificar consultas complexas, há algumas armadilhas comuns das quais você deve estar ciente. Eles incluem o seguinte:

  • Loops infinitos em CTEs recursivos: Se a condição de encerramento de um CTE recursivo não for atendida, isso poderá resultar em um loop infinito, fazendo com que a consulta seja executada indefinidamente. Para evitar que o CTE recursivo seja executado infinitamente, use a dica OPTION (MAXRECURSION N) para limitar o número máximo de iterações recursivas, em que N é um limite especificado.

  • Considerações sobre o desempenho: Os CTEs recursivos podem consumir muitos recursos se a profundidade da recursão for alta ou se grandes conjuntos de dados estiverem sendo processados. Para otimizar o desempenho, limite os dados processados em cada iteração e garanta a filtragem adequada para evitar níveis excessivos de recursão.

Quando usar CTEs em vez de CTEs. Outras técnicas

Embora os CTEs sejam apropriados para simplificar as consultas que envolvem tarefas repetidas, as tabelas derivadas, as exibições e as tabelas temporárias também têm finalidades semelhantes. A tabela a seguir destaca as vantagens e desvantagens de cada método e quando você deve usar cada um deles.

Técnica Vantagens Desvantagens Caso de uso adequado
CTEs Escopo temporário em uma única consultaSem necessidade de armazenamento ou manutençãoMelhora a legibilidade ao modularizar o código Limitados à consulta em que são definidos Organização de consultas complexas, transformações temporárias e decomposição de operações em várias etapas
Tabelas derivadas Simplifica as subconsultas aninhadasNão há necessidade de armazenamento permanente Mais difícil de ler/manter para consultas complexasNão pode ser reutilizado várias vezes em uma consulta Transformações e agregações rápidas e de uso único em uma consulta
Visualizações Reutilizável entre consultasPode aumentar a segurança restringindo o acesso aos dados Requer manutenção e pode afetar várias consultasVisualizações complexas podem afetar o desempenho Lógica reutilizável de longo prazo e controle de acesso a dados

Conclusão

Dominar os CTEs requer prática, como qualquer outra coisa: Recomendo que você experimente o curso de carreira Associate Data Analyst in SQL da DataCamp para se tornar um analista de dados proficiente. O curso Reporting in SQL também ajudará você a se tornar proficiente na criação de relatórios e painéis complexos para a apresentação eficaz de dados. Por fim, você deve obter a Certificação SQL Associate para demonstrar seu domínio no uso do SQL para resolver problemas de negócios e se destacar entre outros profissionais.

Torne-se certificado em SQL

Comprove que suas habilidades em SQL estão prontas para o trabalho com uma certificação.
Impulsionar Minha Carreira

Photo of Allan Ouko
Author
Allan Ouko
LinkedIn
Eu crio artigos que simplificam a ciência e a análise de dados, tornando-as fáceis de entender e acessíveis.

Perguntas frequentes sobre o SQL CTE

O que é um CTE no SQL?

Uma CTE (expressão de tabela comum) é um conjunto de resultados temporário e nomeado definido em uma consulta SQL usando a palavra-chave WITH, que é usada para simplificar consultas complexas, dividindo-as em partes menores e mais gerenciáveis.

Qual é a diferença entre um CTE e uma visualização?

Os CTEs são temporários e existem apenas durante uma única consulta. As visualizações são armazenadas no banco de dados e podem ser reutilizadas em várias consultas. Os CTEs não consomem espaço de armazenamento, enquanto as exibições consomem.

Os CTEs são mais rápidos do que as tabelas temporárias?

Não necessariamente. Os CTEs melhoram a legibilidade, mas nem sempre têm um desempenho melhor do que as tabelas temporárias para grandes conjuntos de dados.

Os CTEs podem ser usados em operações INSERT, UPDATE ou DELETE?

Sim, os CTEs podem ser usados em instruções de modificação de dados para simplificar o processo, especialmente quando há filtragem ou união de dados envolvida.

Qual é a diferença entre CTEs não recursivos e recursivos?

Os CTEs não recursivos não fazem referência a si mesmos e agem de forma semelhante a uma subconsulta ou tabela temporária. Os CTEs não recursivos simplificam consultas complexas semelhantes a subconsultas ou tabelas temporárias. Os CTEs recursivos, por outro lado, fazem referência a si mesmos na definição da consulta e são usados para processamento iterativo de dados, como percorrer estruturas de dados hierárquicas. Eles são apropriados para tarefas que exigem execução repetida, sendo que cada etapa se baseia na anterior.

Temas

Aprenda SQL com a DataCamp

curso

Introduction to SQL

2 hr
900K
Learn how to create and query relational databases using SQL in just two hours.
Ver DetalhesRight Arrow
Iniciar Curso
Ver maisRight Arrow
Relacionado

tutorial

Exemplos e tutoriais de consultas SQL

Se você deseja começar a usar o SQL, nós o ajudamos. Neste tutorial de SQL, apresentaremos as consultas SQL, uma ferramenta poderosa que nos permite trabalhar com os dados armazenados em um banco de dados. Você verá como escrever consultas SQL, aprenderá sobre
Sejal Jaiswal's photo

Sejal Jaiswal

21 min

tutorial

Como usar um alias SQL para simplificar suas consultas

Explore como o uso de um alias SQL simplifica os nomes de colunas e tabelas. Saiba por que usar um alias SQL é fundamental para melhorar a legibilidade e gerenciar uniões complexas.
Allan Ouko's photo

Allan Ouko

9 min

tutorial

Tutorial de visão geral do banco de dados SQL

Neste tutorial, você aprenderá sobre bancos de dados em SQL.
DataCamp Team's photo

DataCamp Team

3 min

tutorial

Como usar GROUP BY e HAVING no SQL

Um guia intuitivo para você descobrir os dois comandos SQL mais populares para agregar linhas do seu conjunto de dados
Eugenia Anello's photo

Eugenia Anello

6 min

tutorial

SELEÇÃO de várias colunas no SQL

Saiba como selecionar facilmente várias colunas de uma tabela de banco de dados em SQL ou selecionar todas as colunas de uma tabela em uma consulta simples.
DataCamp Team's photo

DataCamp Team

3 min

tutorial

Tutorial de SQLAlchemy com exemplos

Aprenda a acessar e executar consultas SQL em todos os tipos de bancos de dados relacionais usando objetos Python.
Abid Ali Awan's photo

Abid Ali Awan

13 min

See MoreSee More