Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Apresentando expressões de tabela comuns no SQL Server


Common Table Expressions, ou CTE, é simplesmente uma técnica para criar um conjunto temporário de registros que podem ser referenciados em uma instrução INSERT, SELECT, UPDATE ou DELETE.

As expressões de tabela comuns foram introduzidas pela Microsoft no SQL Server 2005. Elas não são armazenadas como objetos na memória do banco de dados, pois sua vida útil é igual ao tempo de execução da consulta. Assim que uma consulta é concluída, eles são removidos da memória do banco de dados. O CTE pode ser referenciado em uma consulta quantas vezes você quiser e também pode ser auto-referenciado.



Vamos criar um banco de dados com uma tabela de alunos e inserir alguns registros de alunos fictícios nela. Usaremos esse banco de dados para escrever consultas CTE. Como sempre, certifique-se de ter um backup completo antes de experimentar um novo código. Consulte este artigo sobre backup do SQL se não tiver certeza.

Execute as seguintes consultas em seu servidor.
CREATE DATABASE schooldb

CREATE TABLE student
(
    id INT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    gender VARCHAR(50) NOT NULL,
    DOB datetime NOT NULL,
    total_score INT NOT NULL,
    
 )

INSERT INTO student

VALUES (1, 'Jolly', 'Female', '12-JUN-1989', 500), 
(2, 'Jon', 'Male', '02-FEB-1974', 545), 
(3, 'Sara', 'Female', '07-MAR-1988', 600), 
(4, 'Laura', 'Female', '22-DEC-1981', 400), 
(5, 'Alan', 'Male', '29-JUL-1993', 500), 
(6, 'Kate', 'Female', '03-JAN-1985', 500), 
(7, 'Joseph', 'Male', '09-APR-1982', 643), 
(8, 'Mice', 'Male', '16-AUG-1974', 543), 
(9, 'Wise', 'Male', '11-NOV-1987', 499), 
(10, 'Elis', 'Female', '28-OCT-1990', 400);

Agora, vamos criar uma expressão de tabela comum muito simples. Este CTE conterá registros de todos os alunos que nasceram antes de 1º de janeiro de 1985. Dê uma olhada no roteiro a seguir.
USE schooldb;

WITH OldStudents AS
(
SELECT * FROM student
WHERE DOB < '1985-01-01'
)

Para criar um CTE, você deve começar com a palavra-chave 'WITH' seguida do nome do CTE e da palavra-chave 'AS'.

A seguir, dentro dos parênteses, deve-se escrever a consulta que retorna os registros que o CTE armazenará temporariamente. No script acima, criamos um CTE chamado “OldStudents”.

No entanto, observe que, se você tentar executar a consulta acima, receberá um erro. Isso ocorre porque uma vez que você cria um CTE, você deve usá-lo imediatamente.

Vamos selecionar todos os registros do nosso recém-criado CTE “OldStudents”. Tente o seguinte script em seu servidor.
USE schooldb;

WITH OldStudents AS
(
	SELECT * FROM student
	WHERE DOB < '1985-01-01'

)

SELECT * FROM OldStudents

O script acima recuperará o seguinte conjunto de registros:


Calculando Agregado via CTE


Assim como as tabelas, você pode executar funções agregadas no CTE. Vamos dar uma olhada em outro exemplo de CTE.
USE schooldb;

WITH SumofScores AS
(
	SELECT 
		gender, SUM(total_score) as SumScore
	FROM student
	GROUP BY gender
)

SELECT AVG (SumScore)
FROM SumofScores

No exemplo acima, criamos um CTE chamado SumofScores. Este CTE contém a soma dos valores armazenados na coluna total_score da tabela do aluno. O resultado é agrupado pela coluna de gênero. Os dados armazenados pelo CTE ficam assim na memória:



Em seguida, realizamos a função AVG na coluna “SumScore” do CTE. O resultado final do script será a média de 2400 e 2730, ou seja, 2565.

Isso é um pouco mais complicado do que o exemplo anterior, mas demonstra o conceito de CTE com mais clareza.

Colunas de rotulagem no CTE


No exemplo anterior, adicionamos um alias à segunda coluna do CTE. Nós o renomeamos como “SumScore”. Essa é uma maneira de rotular colunas no CTE e é semelhante aos aliases de coluna da tabela.

No entanto, há outra maneira de definir nomes de colunas no CTE. Dê uma olhada na consulta a seguir.
USE schooldb;

WITH SumofScores(Gender, SumScore) AS
(
	SELECT 
		gender, SUM(total_score)
	FROM student
	GROUP BY gender
)

SELECT AVG (SumScore)
From SumofScores

Neste script, adicionamos os nomes das colunas do CTE “SumofScores” entre parênteses após o nome do CTE. Cada nome de coluna é separado por uma vírgula.

Se você observar a instrução SELECT após o CTE, poderá ver que estamos referenciando a coluna “SumScore” que criamos entre parênteses após o nome do CTE.

Criando vários CTEs


Todos os exemplos até agora usaram apenas uma única expressão de tabela comum para maior clareza. Você pode criar uma lista de CTEs ao mesmo tempo e usar todos eles em combinação no conjunto de resultados final.

Isso é melhor explicado com a ajuda de um exemplo. Dê uma olhada no seguinte script abaixo.

Aqui vamos criar dois CTEs. O primeiro CTE armazenará todos os registros dos alunos nascidos antes de 1º de janeiro de 1985. O segundo CTE conterá todos os registros dos alunos nascidos em ou após 1º de janeiro de 1985.

Depois disso, usaremos instruções select para recuperar todos os registros de ambas as CTEs. Os registros recuperados serão mesclados usando a instrução UNION. Por fim, o registro mesclado será classificado em ordem crescente de data de nascimento.
USE schooldb;

WITH OldStudents AS
(
	SELECT * FROM student
	WHERE DOB < '1985-01-01'

),

YoungStudents AS
(
	SELECT * FROM student
	WHERE DOB >= '1985-01-01'

)

(SELECT * FROM OldStudents
UNION
SELECT * FROM YoungStudents)

ORDER BY DOB

Na consulta SQL acima, criamos dois CTEs:“OldStudents” e “YoungStudents”. Vale ressaltar que você não precisa usar a palavra-chave “WITH” em cada CTE. Você só precisa usá-lo antes do primeiro CTE no script, depois disso você pode criar qualquer número de CTEs separando-os com uma vírgula.

O script acima recupera os seguintes resultados: