Introdução
Neste laboratório, você explorará o poder das Funções de Janela (Window Functions) do MySQL. Você aprenderá a realizar cálculos em conjuntos de linhas de tabelas que estão relacionadas à linha atual.
Você começará criando um conjunto de dados de exemplo e, em seguida, usará funções como ROW_NUMBER(), SUM(), AVG() e LAG(), combinadas com a cláusula OVER(), para realizar análises de dados avançadas. Este laboratório fornece exemplos práticos, passo a passo, para ajudá-lo a entender e aplicar essas funções poderosas.
Configurar o Banco de Dados e a Tabela
Antes de usar funções de janela (window functions), você precisa de um banco de dados e uma tabela com dados de exemplo. Nesta etapa, você criará um banco de dados chamado company e uma tabela chamada employees.
Primeiro, abra o terminal a partir da sua área de trabalho.
Conecte-se ao servidor MySQL como o usuário root. Como este é um ambiente de laboratório, você pode usar sudo para se conectar sem senha.
sudo mysql -u root
Uma vez conectado, você verá o prompt do MySQL (mysql>).
Agora, crie o banco de dados company e mude para ele. A cláusula IF NOT EXISTS impede um erro se o banco de dados já existir.
CREATE DATABASE IF NOT EXISTS company;
USE company;
Em seguida, crie a tabela employees. Esta tabela armazenará o ID do funcionário, nome, departamento e salário.
CREATE TABLE IF NOT EXISTS employees (
employee_id INT PRIMARY KEY,
employee_name VARCHAR(50),
department VARCHAR(50),
salary DECIMAL(10, 2)
);
Agora, insira alguns dados de exemplo na tabela employees.
INSERT INTO employees (employee_id, employee_name, department, salary) VALUES
(1, 'Alice', 'Sales', 60000.00),
(2, 'Bob', 'Marketing', 55000.00),
(3, 'Charlie', 'Sales', 65000.00),
(4, 'David', 'IT', 70000.00),
(5, 'Eve', 'Marketing', 62000.00)
ON DUPLICATE KEY UPDATE
employee_name = VALUES(employee_name),
department = VALUES(department),
salary = VALUES(salary);
Para verificar se os dados foram inseridos corretamente, você pode visualizar todas as linhas da tabela employees.
SELECT * FROM employees;
A saída deve exibir os cinco registros que você inseriu:
+-------------+---------------+------------+----------+
| employee_id | employee_name | department | salary |
+-------------+---------------+------------+----------+
| 1 | Alice | Sales | 60000.00 |
| 2 | Bob | Marketing | 55000.00 |
| 3 | Charlie | Sales | 65000.00 |
| 4 | David | IT | 70000.00 |
| 5 | Eve | Marketing | 62000.00 |
+-------------+---------------+------------+----------+
5 rows in set (0.00 sec)
Com o banco de dados e a tabela prontos, você pode prosseguir para a próxima etapa para aprender sobre funções de janela.
Classificar Linhas com ROW_NUMBER()
A função ROW_NUMBER() atribui um inteiro sequencial único a cada linha dentro de uma partição de um conjunto de resultados. É comumente usada para classificação (ranking) e paginação.
A sintaxe básica é:
ROW_NUMBER() OVER (ORDER BY column_name [ASC|DESC])
OVER(): Esta cláusula define a janela (o conjunto de linhas) para a função.ORDER BY: Esta cláusula, dentro deOVER(), especifica a ordem em que os números das linhas são atribuídos.
Continuando no shell do MySQL, você agora usará ROW_NUMBER() para classificar os funcionários por seus salários em ordem decrescente.
SELECT
employee_name,
department,
salary,
ROW_NUMBER() OVER (ORDER BY salary DESC) AS salary_rank
FROM
employees;
Esta consulta adiciona uma coluna salary_rank, numerando os funcionários do maior para o menor salário.
+---------------+------------+----------+-------------+
| employee_name | department | salary | salary_rank |
+---------------+------------+----------+-------------+
| David | IT | 70000.00 | 1 |
| Charlie | Sales | 65000.00 | 2 |
| Eve | Marketing | 62000.00 | 3 |
| Alice | Sales | 60000.00 | 4 |
| Bob | Marketing | 55000.00 | 5 |
+---------------+------------+----------+-------------+
5 rows in set (0.00 sec)
Como você pode ver, David tem a classificação 1 porque tem o maior salário. Isso demonstra como ROW_NUMBER() pode ser usada para criar uma classificação simples.
Calcular um Total Acumulado com SUM()
Um total acumulado, ou soma cumulativa, é a soma de uma sequência de números que é atualizada à medida que cada novo número é adicionado. Em SQL, você pode calcular isso usando SUM() OVER().
A sintaxe é:
SUM(column_name) OVER (ORDER BY column_name [ASC|DESC])
Esta função soma os valores de uma coluna na ordem especificada pela cláusula ORDER BY.
Agora, vamos calcular o total acumulado dos salários, ordenados por employee_id.
SELECT
employee_name,
salary,
SUM(salary) OVER (ORDER BY employee_id) AS running_total
FROM
employees;
O resultado mostrará o salário de cada funcionário e a soma cumulativa até aquela linha.
+---------------+----------+---------------+
| employee_name | salary | running_total |
+---------------+----------+---------------+
| Alice | 60000.00 | 60000.00 |
| Bob | 55000.00 | 115000.00 |
| Charlie | 65000.00 | 180000.00 |
| David | 70000.00 | 250000.00 |
| Eve | 62000.00 | 312000.00 |
+---------------+----------+---------------+
5 rows in set (0.00 sec)
Por exemplo, o running_total para Bob é a soma do salário dele e do salário de Alice (60000.00 + 55000.00 = 115000.00). Isso é útil para acompanhar métricas cumulativas como vendas ou despesas ao longo do tempo.
Agrupar Cálculos com PARTITION BY
A cláusula PARTITION BY divide o conjunto de resultados em partições (grupos) e aplica a função de janela a cada partição independentemente. Isso é útil para realizar cálculos dentro de categorias específicas.
A sintaxe é:
function() OVER (PARTITION BY column_name ORDER BY ...)
Vamos usar PARTITION BY para classificar os funcionários dentro de cada departamento com base em seus salários.
SELECT
employee_name,
department,
salary,
ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rank_in_dept
FROM
employees;
Esta consulta particiona os dados por department e, em seguida, classifica os funcionários em cada departamento por salário.
+---------------+------------+----------+--------------+
| employee_name | department | salary | rank_in_dept |
+---------------+------------+----------+--------------+
| David | IT | 70000.00 | 1 |
| Eve | Marketing | 62000.00 | 1 |
| Bob | Marketing | 55000.00 | 2 |
| Charlie | Sales | 65000.00 | 1 |
| Alice | Sales | 60000.00 | 2 |
+---------------+------------+----------+--------------+
5 rows in set (0.00 sec)
Observe que a classificação é reiniciada para cada departamento. Por exemplo, tanto Eve quanto Charlie são classificados como 1, mas dentro de seus respectivos departamentos 'Marketing' e 'Sales'. Isso permite uma análise mais granular em comparação com uma classificação global.
Comparar Linhas com LAG()
A função LAG() fornece acesso a uma linha em um deslocamento físico especificado que vem antes da linha atual. É útil para comparar um valor na linha atual com um valor em uma linha anterior.
A sintaxe é:
LAG(expression, offset, default_value) OVER (ORDER BY ...)
expression: A coluna ou expressão a ser recuperada.offset: O número de linhas a serem retrocedidas (o padrão é 1).default_value: O valor a ser retornado se o deslocamento estiver fora dos limites (por exemplo, para a primeira linha).
Vamos encontrar o salário do funcionário anterior na lista, ordenado por employee_id.
SELECT
employee_name,
salary,
LAG(salary) OVER (ORDER BY employee_id) AS previous_salary
FROM
employees;
Esta consulta recupera o salário da linha anterior. Para a primeira linha, onde não há linha anterior, ela retorna NULL.
+---------------+----------+-----------------+
| employee_name | salary | previous_salary |
+---------------+----------+-----------------+
| Alice | 60000.00 | NULL |
| Bob | 55000.00 | 60000.00 |
| Charlie | 65000.00 | 55000.00 |
| David | 70000.00 | 65000.00 |
| Eve | 62000.00 | 70000.00 |
+---------------+----------+-----------------+
5 rows in set (0.00 sec)
Você pode usar isso para calcular a diferença entre salários consecutivos. Quando o salário anterior for NULL (para a primeira linha), o resultado também será NULL.
SELECT
employee_name,
salary,
salary - LAG(salary) OVER (ORDER BY employee_id) AS salary_diff
FROM
employees;
Esta consulta calcula a diferença entre o salário do funcionário atual e o anterior.
+---------------+----------+-------------+
| employee_name | salary | salary_diff |
+---------------+----------+-------------+
| Alice | 60000.00 | NULL |
| Bob | 55000.00 | -5000.00 |
| Charlie | 65000.00 | 10000.00 |
| David | 70000.00 | 5000.00 |
| Eve | 62000.00 | -8000.00 |
+---------------+----------+-------------+
5 rows in set (0.00 sec)
Você praticou agora várias funções de janela chave. Você pode sair do shell do MySQL.
exit;
Resumo
Neste laboratório, você explorou o uso de funções de janela do MySQL. Você aprendeu como atribuir números de linha usando ROW_NUMBER(), calcular totais acumulados com SUM() OVER(), realizar cálculos em grupos específicos usando PARTITION BY e acessar dados de linhas anteriores com LAG().
Ao aplicar essas funções a um conjunto de dados de exemplo, você ganhou experiência prática na realização de análises de dados avançadas diretamente em suas consultas SQL. Estas são habilidades valiosas para gerar relatórios e insights complexos a partir de seus dados.



