Retornando dados do registro anterior ou seguinte com SQL
Neste artigo vamos ver como podemos utilizar informações do registro anterior e do próximo registro utilizando SQL. Vamos ver exemplos utilizando MySQL e SQL Server.
Os dados que vamos utilizar são o número de novos emplacamentos de veículos leves no Brasil durante os anos de 2021 e 2022. Vamos criar uma tabela onde este valor vai ser registrado por mês.
O que você vai aprender neste artigo?
* Como retornar dados da linha de resultados anterior utilizando a função LAG.
* Como retornar dados da linha de resultados seguinte utilizando a função LEAD.
Nosso primeiro passo é criar uma tabela para guardar estas informações.
MySQL
CREATE TABLE veiculos (
id int NOT NULL AUTO_INCREMENT,
ano int,
mes int,
quantidade int,
PRIMARY KEY (id)
);
SQL Server
CREATE TABLE veiculos (
id int IDENTITY(1,1) PRIMARY KEY,
ano int,
mes int,
quantidade int
);
Os dados que serão utilizados neste artigo são os seguintes:
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2021, 1, 162804);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2021, 2, 158470);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2021, 3, 177356);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2021, 4, 164090);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2021, 5, 175691);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2021, 6, 169847);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2021, 7, 162241);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2021, 8, 158267);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2021, 9, 142144);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2021, 10, 149899);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2021, 11, 160748);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2021, 12, 193283);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2022, 1, 116455);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2022, 2, 121026);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2022, 3, 134699);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2022, 4, 136136);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2022, 5, 174584);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2022, 6, 165972);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2022, 7, 168857);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2022, 8, 193326);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2022, 9, 180110);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2022, 10, 168276);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2022, 11, 191562);
INSERT INTO veiculos (ano, mes, quantidade) VALUES (2022, 12, 201791);
Retornar dados da linha de resultados anterior utilizando LAG.
A sintaxe da função LAG é a seguinte:
LAG(nome_do_campo, OffSet) OVER (
PARTITION BY nome_do_campo
ORDER BY nome_do_campo [ASC|DESC]
);
A função LAG possui dois parâmetros, o primeiro recebe o nome do campo que você deseja retornar informações. O segundo parâmetro é opcional, nele você deve retornar qual o registro anterior que você quer. Por padrão o valor é 1, ou seja, o primeiro registro anterior ao atual.
Após a função LAG você deve obrigatoriamente utilizar a função OVER(). Esta função é utilizada quando você quer particionar os resultados. No MySQL seus parãmetros não são obrigatórios, no SQL Server você deve informar pelo menos 1 deles. PARTITION BY define uma segmentação lógia para os resultados e ORDER BY se aplica a esta segmentação de dados.
No nosso primeiro exemplo, vamos retornar o valor da quantidade da linha anterior. Perceba que nesta consulta estamos ordenando os resultados por ano e mes
MYSQL
SELECT ano, mes, quantidade, LAG(quantidade, 1) OVER () as emplacamentos_anteriores
FROM veiculos
ORDER BY ano, mes
SQL Server
SELECT ano, mes, quantidade, LAG(quantidade, 1) OVER (ORDER BY ano, mes) as emplacamentos_anteriores
FROM veiculos
ORDER BY ano, mes
Como LAG retorna os dados da linha anterior, o primeiro valor do campo emplacamentos_anteriores vai estar como nulo.
O nosso objetivo é retornar a diferença entre a linha atual é a anterior, desta forma vamos ajustar a nossa consulta para que ela fique desta forma:
MySQL
SELECT ano, mes, quantidade, quantidade - LAG(quantidade, 1) OVER () as resultado
FROM veiculos
ORDER BY ano, mes
SQL Server
SELECT ano, mes, quantidade, quantidade - LAG(quantidade, 1) OVER (ORDER BY ano, mes) as resultado
FROM veiculos
ORDER BY ano, mes
Com base nos resultados, você vai ver que em fevereiro de 2021 foram emplacados menos 4334 veículos em relação ao mês de janeiro de 2021.
Vamos ver um exemplo de particionamento de dados. Nosso objetivo agora é comparar os emplacamentos por mês agrupados por ano. Desta forma, será necessário particionar os dados por mes e ordenar po mes. A nossa consulta foi alterada para ordenar os dados primeiro por mês e depois por ano.
SELECT ano, mes, quantidade, quantidade - LAG(quantidade, 1) OVER (PARTITION BY mes ORDER BY ano, mes) as resultado
FROM veiculos
ORDER BY mes, ano
Perceba que nestes resultados a coluna resultado referente ao ano de 2021 deve mostrar valores nulos.
Retornar dados da linha de resultados anterior utilizando LEAD.
Agora que você viu como retornar os registros da linha anterior vamos fazer a operação contrária. Para isso, vamos utilizar a função LEAD. A função LEAD tem a mesma sintaxe da função LAG, a diferença é que ao invés de retornar a linha anterior ele retorna a linha seguinte. No exemplo a seguir retornaremos os dados da linha seguinte
MySQL
SELECT ano, mes, quantidade, LEAD(quantidade, 1) OVER () as emplacamentos_mes_seguinte
FROM veiculos
ORDER BY ano, mes
SQL Server
SELECT ano, mes, quantidade, LEAD(quantidade, 1) OVER (ORDER BY ano, mes) as
emplacamentos_mes_seguinte
FROM veiculos
ORDER BY ano, mes
Perceba que a úlitma linha retornou o valor do campo emplacamentos_mes_seguinte como nulo.
Da mesma forma que fizemos com LAG, o que queremos não é o valor do campo seguinte, mas a diferença em relação a linha atual. Desta forma, faremos a subtração da quantidade atual pela quantidade da linha seguinte
MySQL
SELECT ano, mes, quantidade, quantidade - LEAD(quantidade, 1) OVER () as resultado
FROM veiculos
ORDER BY ano, mes
SQL Server
SELECT ano, mes, quantidade, quantidade - LEAD(quantidade, 1) OVER (ORDER BY ano, mes) as resultado
FROM veiculos
ORDER BY ano, mes
Você vai perceber que no caso de janeiro 2021 foram emplacados 4334 veiculos a mais do que no mês seguinte.
Para encerrar, vamos fazer o particionamento dos resultados, comparando os mesmos meses de anos diferentes.
SELECT ano, mes, quantidade, quantidade - LEAD(quantidade, 1) OVER (PARTITION BY mes ORDER BY ano, mes) as resultado
FROM veiculos
ORDER BY mes, ano
Como fizemos o particionamento de dados considerando o mês e a nossa consulta foi ordenada por mês e ano, o campo resultado referente aos meses de 2022 deve estar nulo.