Na análise de dados e na elaboração de relatórios usando SQL, muitas vezes é necessário obter o primeiro ou o último valor de um conjunto de dados. Para facilitar isso, as funções FIRST_VALUE e LAST_VALUE são muito úteis. Neste artigo, vamos detalhar como usar essas funções para manipular dados de forma eficiente, incluindo exemplos práticos.
Uso básico da função FIRST_VALUE
A função FIRST_VALUE é utilizada para obter o primeiro valor dentro de uma janela ou partição especificada. Isso permite extrair facilmente o valor da primeira linha do conjunto de dados.
Sintaxe básica
SELECT
column1,
FIRST_VALUE(column1) OVER (PARTITION BY column2 ORDER BY column3) AS first_value
FROM
table_name;
Neste exemplo, obtemos o primeiro valor de column1
após particionar os dados por column2
e ordená-los por column3
.
Exemplo de uso
Por exemplo, se quisermos obter os nomes dos primeiros funcionários contratados em cada departamento em um banco de dados de funcionários, usamos a seguinte consulta:
SELECT
department,
employee_name,
FIRST_VALUE(employee_name) OVER (PARTITION BY department ORDER BY hire_date) AS first_hired
FROM
employees;
Esta consulta retorna o nome do funcionário que foi contratado primeiro em cada departamento.
Exemplos de aplicação da função FIRST_VALUE
A função FIRST_VALUE não é útil apenas em casos simples, mas também em consultas e análises mais complexas. Aqui, apresentamos exemplos aplicados a um conjunto de dados real.
Obter a primeira data de venda dos dados de vendas
Por exemplo, se quisermos obter a primeira data de venda de cada loja a partir dos dados de vendas de um produto, usamos a seguinte consulta:
SELECT
store_id,
product_id,
sale_date,
FIRST_VALUE(sale_date) OVER (PARTITION BY store_id, product_id ORDER BY sale_date) AS first_sale_date
FROM
sales;
Esta consulta retorna a primeira data de venda para cada loja e cada produto.
Obter o primeiro resultado de exame dos dados de notas de estudantes
Quando gerenciamos dados de notas de estudantes, podemos obter o primeiro resultado de exame de cada estudante.
SELECT
student_id,
exam_date,
score,
FIRST_VALUE(score) OVER (PARTITION BY student_id ORDER BY exam_date) AS first_exam_score
FROM
exam_results;
Esta consulta retorna a primeira pontuação de exame de cada estudante.
Obter o primeiro valor de compra dos dados de transações
Este exemplo mostra como obter o primeiro valor de compra a partir dos dados de transações de clientes.
SELECT
customer_id,
transaction_date,
amount,
FIRST_VALUE(amount) OVER (PARTITION BY customer_id ORDER BY transaction_date) AS first_purchase_amount
FROM
transactions;
Esta consulta retorna o primeiro valor de compra de cada cliente.
Uso básico da função LAST_VALUE
A função LAST_VALUE é usada para obter o último valor dentro de uma janela ou partição especificada. Isso permite extrair facilmente o valor da última linha do conjunto de dados.
Sintaxe básica
SELECT
column1,
LAST_VALUE(column1) OVER (PARTITION BY column2 ORDER BY column3 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_value
FROM
table_name;
Neste exemplo, obtemos o último valor de column1
após particionar os dados por column2
e ordená-los por column3
. É importante usar a cláusula ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
para especificar a janela inteira.
Exemplo de uso
Por exemplo, se quisermos obter os nomes dos últimos funcionários contratados em cada departamento em um banco de dados de funcionários, usamos a seguinte consulta:
SELECT
department,
employee_name,
LAST_VALUE(employee_name) OVER (PARTITION BY department ORDER BY hire_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_hired
FROM
employees;
Esta consulta retorna o nome do funcionário que foi contratado por último em cada departamento.
Exemplos de aplicação da função LAST_VALUE
A função LAST_VALUE é tão útil quanto a função FIRST_VALUE em análises de dados e elaboração de relatórios. Aqui, apresentamos exemplos aplicados a um conjunto de dados real.
Obter a última data de venda dos dados de vendas
Por exemplo, se quisermos obter a última data de venda de cada loja a partir dos dados de vendas de um produto, usamos a seguinte consulta:
SELECT
store_id,
product_id,
sale_date,
LAST_VALUE(sale_date) OVER (PARTITION BY store_id, product_id ORDER BY sale_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_sale_date
FROM
sales;
Esta consulta retorna a última data de venda para cada loja e cada produto.
Obter o último resultado de exame dos dados de notas de estudantes
Quando gerenciamos dados de notas de estudantes, podemos obter o último resultado de exame de cada estudante.
SELECT
student_id,
exam_date,
score,
LAST_VALUE(score) OVER (PARTITION BY student_id ORDER BY exam_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_exam_score
FROM
exam_results;
Esta consulta retorna a última pontuação de exame de cada estudante.
Obter o último valor de compra dos dados de transações
Este exemplo mostra como obter o último valor de compra a partir dos dados de transações de clientes.
SELECT
customer_id,
transaction_date,
amount,
LAST_VALUE(amount) OVER (PARTITION BY customer_id ORDER BY transaction_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_purchase_amount
FROM
transactions;
Esta consulta retorna o último valor de compra de cada cliente.
Combinação de FIRST_VALUE e LAST_VALUE
Ao combinar as funções FIRST_VALUE e LAST_VALUE, é possível obter simultaneamente os primeiros e últimos valores de um conjunto de dados. Isso possibilita, por exemplo, comparar os valores no início e no final de um período, permitindo uma análise mais avançada.
Obter a primeira e a última data de venda dos dados de vendas
Por exemplo, para obter a primeira e a última data de venda de cada loja a partir dos dados de vendas, a consulta é a seguinte:
SELECT
store_id,
product_id,
FIRST_VALUE(sale_date) OVER (PARTITION BY store_id, product_id ORDER BY sale_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_sale_date,
LAST_VALUE(sale_date) OVER (PARTITION BY store_id, product_id ORDER BY sale_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_sale_date
FROM
sales;
Esta consulta retorna a primeira e a última data de venda para cada loja e cada produto.
Obter a primeira e a última data de contratação de funcionários
Quando obtemos a primeira e a última data de contratação em um banco de dados de funcionários, usamos a seguinte consulta:
SELECT
department,
employee_name,
FIRST_VALUE(hire_date) OVER (PARTITION BY department ORDER BY hire_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_hire_date,
LAST_VALUE(hire_date) OVER (PARTITION BY department ORDER BY hire_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_hire_date
FROM
employees;
Esta consulta retorna o nome do funcionário que foi contratado primeiro e o que foi contratado por último em cada departamento.
Obter o primeiro e o último valor de compra de transações de clientes
Esta consulta é usada para obter o primeiro e o último valor de compra a partir dos dados de transações de clientes.
SELECT
customer_id,
FIRST_VALUE(amount) OVER (PARTITION BY customer_id ORDER BY transaction_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_purchase_amount,
LAST_VALUE(amount) OVER (PARTITION BY customer_id ORDER BY transaction_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_purchase_amount
FROM
transactions;
Esta consulta retorna o primeiro e o último valor de compra de cada cliente.
Uso como funções de janela
As funções FIRST_VALUE e LAST_VALUE podem ser usadas como funções de janela, permitindo uma análise e manipulação de dados mais flexíveis. Usadas como funções de janela, podem calcular os primeiros e últimos valores para cada linha e retornar isso como resultado.
Conceito básico de funções de janela
As funções de janela realizam cálculos sobre o conjunto de resultados de uma consulta e se aplicam a linhas dentro de uma janela específica. A janela é definida usando as cláusulas PARTITION BY e ORDER BY.
Sintaxe básica
SELECT
column1,
FIRST_VALUE(column1) OVER (PARTITION BY column2 ORDER BY column3 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_value,
LAST_VALUE(column1) OVER (PARTITION BY column2 ORDER BY column3 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_value
FROM
table_name;
Nesta sintaxe, particionamos os dados por column2
e obtemos os primeiros e últimos valores de column1
após ordená-los por column3
.
Exemplo de uso: funções de janela em dados de vendas
Por exemplo, para obter a primeira e a última data de venda usando funções de janela nos dados de vendas de cada loja, usamos a seguinte consulta:
SELECT
store_id,
product_id,
sale_date,
FIRST_VALUE(sale_date) OVER (PARTITION BY store_id ORDER BY sale_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_sale_date,
LAST_VALUE(sale_date) OVER (PARTITION BY store_id ORDER BY sale_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_sale_date
FROM
sales;
Esta consulta retorna a primeira e a última data de venda para cada loja.
Exemplo de uso: dados de notas de estudantes
Para obter o primeiro e o último resultado de exame para cada estudante em dados de notas, usamos a seguinte consulta:
SELECT
student_id,
exam_date,
score,
FIRST_VALUE(score) OVER (PARTITION BY student_id ORDER BY exam_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_exam_score,
LAST_VALUE(score) OVER (PARTITION BY student_id ORDER BY exam_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_exam_score
FROM
exam_results;
Esta consulta retorna o primeiro e o último resultado de exame para cada estudante.
Uso de PARTITION BY e ORDER BY
Uma das características poderosas das funções FIRST_VALUE e LAST_VALUE é a capacidade de particionar e ordenar os dados. Isso permite obter os primeiros e últimos valores dentro de grupos específicos.
Conceito básico de particionamento
O particionamento consiste em agrupar os dados de acordo com critérios específicos. Isso permite realizar cálculos independentes dentro de cada grupo. O particionamento é realizado usando a cláusula PARTITION BY.
Conceito básico de ORDER BY
A cláusula ORDER BY é utilizada para ordenar as linhas dentro de cada partição em uma ordem específica. Isso permite identificar corretamente os primeiros e últimos valores.
Exemplo de uso de particionamento e ORDER BY
A seguir está uma consulta para obter a primeira e a última data de venda para cada loja a partir dos dados de vendas.
SELECT
store_id,
product_id,
sale_date,
FIRST_VALUE(sale_date) OVER (PARTITION BY store_id, product_id ORDER BY sale_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_sale_date,
LAST_VALUE(sale_date) OVER (PARTITION BY store_id, product_id ORDER BY sale_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_sale_date
FROM
sales;
Esta consulta retorna a primeira e a última data de venda para cada loja e cada produto.
Exemplo de aplicação em dados de estudantes
Para obter o primeiro e o último resultado de exame para cada estudante em dados de notas, usamos a seguinte consulta:
SELECT
student_id,
exam_date,
score,
FIRST_VALUE(score) OVER (PARTITION BY student_id ORDER BY exam_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_exam_score,
LAST_VALUE(score) OVER (PARTITION BY student_id ORDER BY exam_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_exam_score
FROM
exam_results;
Esta consulta retorna o primeiro e o último resultado de exame para cada estudante.
Exercícios e respostas
Para aprofundar sua compreensão das funções FIRST_VALUE e LAST_VALUE, preparamos alguns exercícios. Para cada exercício, também apresentamos uma solução, então sinta-se à vontade para experimentá-los.
Exercício 1: Obter as primeiras e últimas datas de contratação em cada departamento
Crie uma consulta para obter as primeiras e últimas datas de contratação a partir da tabela employees
.
-- tabela employees
+---------+------------+------------+
| emp_id | department | hire_date |
+---------+------------+------------+
| 1 | Sales | 2020-01-01 |
| 2 | Sales | 2021-05-10 |
| 3 | HR | 2019-03-15 |
| 4 | HR | 2020-07-23 |
| 5 | IT | 2021-01-05 |
+---------+------------+------------+
Exemplo de resposta
SELECT
department,
FIRST_VALUE(hire_date) OVER (PARTITION BY department ORDER BY hire_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_hire_date,
LAST_VALUE(hire_date) OVER (PARTITION BY department ORDER BY hire_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_hire_date
FROM
employees;
Exercício 2: Obter as primeiras e últimas datas de venda de cada produto
Crie uma consulta para obter as primeiras e últimas datas de venda a partir da tabela sales
.
-- tabela sales
+---------+------------+------------+
| sale_id | product_id | sale_date |
+---------+------------+------------+
| 1 | 101 | 2022-01-01 |
| 2 | 102 | 2022-01-05 |
| 3 | 101 | 2022-02-01 |
| 4 | 103 | 2022-01-10 |
| 5 | 102 | 2022-03-01 |
+---------+------------+------------+
Exemplo de resposta
SELECT
product_id,
FIRST_VALUE(sale_date) OVER (PARTITION BY product_id ORDER BY sale_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_sale_date,
LAST_VALUE(sale_date) OVER (PARTITION BY product_id ORDER BY sale_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_sale_date
FROM
sales;
Exercício 3: Obter os primeiros e últimos valores de compra de cada cliente
Crie uma consulta para obter os primeiros e últimos valores de compra a partir da tabela transactions
.
-- tabela transactions
+-------------+----------+--------+--------------+
| transaction_id | customer_id | amount | transaction_date |
+-------------+----------+--------+--------------+
| 1 | 1001 | 200 | 2023-01-01 |
| 2 | 1002 | 150 | 2023-01-05 |
| 3 | 1001 | 300 | 2023-02-01 |
| 4 | 1003 | 250 | 2023-01-10 |
| 5 | 1002 | 400 | 2023-03-01 |
+-------------+----------+--------+--------------+
Exemplo de resposta
SELECT
customer_id,
FIRST_VALUE(amount) OVER (PARTITION BY customer_id ORDER BY transaction_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_purchase_amount,
LAST_VALUE(amount) OVER (PARTITION BY customer_id ORDER BY transaction_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS last_purchase_amount
FROM
transactions;
Conclusão
Neste artigo, aprendemos como usar as funções FIRST_VALUE e LAST_VALUE em SQL para obter os primeiros e últimos valores de um conjunto de dados. Abordamos o uso básico, exemplos práticos, uso como funções de janela e também como particionar e ordenar dados. Aproveitando essas funções, a análise de dados e a elaboração de relatórios se tornam mais eficientes. Experimente aplicar essas técnicas em seus próprios conjuntos de dados.