SQL Server 2022 - Função GREATEST()

Olá amigos do Blog,
Depois de um longo tempo sem postar nada por aqui estamos de volta!!
Já tem um tempinho que o SQL Server 2022 lançou e ele trouxe diversas novidades interessantes.
Hoje falaremos um pouco sobre a função T-SQL GREATEST(), esse cara é semelhante a função MAX() que retorna o maior valor de uma tabela, mas diferente dele que permite apenas um argumento, a função GREATEST() lhe permite ver o valor máximo de várias colunas ao mesmo tempo.
Bem, para ilustrar nosso cenário, nada melhor do que fazer uma brincadeira não é?
Iremos fazer hoje o BOLICHE com os líderes da Power Tuning!!!
Primeiramente faremos a criação de uma base de dados chamada BOLICHE (meio óbvio né?, rs)…
CREATE DATABASE BOLICHELogo em seguida, utilizaremos nossa base criada :
USE BOLICHEAgora iremos criar uma tabela com os Jogadores do nosso Jogo :
CREATE TABLE Jogador
(
ID INT IDENTITY PRIMARY KEY,
nome VARCHAR(200),
data_cadastro DATETIME
DEFAULT GETDATE()
);Após criar a tabela iremos popular os jogadores :
INSERT INTO dbo.Jogador
(
nome,
data_cadastro
)
VALUES
( 'Gustavo Larocca', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'Luiz Lima', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'Raiane Flores', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'Walter Cutini', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'Fabrício Lima', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'Dirceu Rezende (agora com Z)', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'Eduardo Rabelo', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'David Styveen', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'Rodrigo Ribeiro', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'Taiany Coelho', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'Wesley Cardoso', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'Raul Oliveira', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'Juliana Quintão', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'Fernanda Caetano', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'Ricardo Portilho', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'Fabiana Lima', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'Rafael Mendonça', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
),
( 'Rafael Santos', -- nome - varchar(200)
DEFAULT -- data_cadastro - datetime
);Agora, iremos criar uma tabela para o nosso jogo, essa tabela se chamará Rodada, teremos o Id do jogador, Id do jogo e o Frame (que representa o valor obtido de cada rodada daquele determinado jogador no jogo).
CREATE TABLE Rodada
(
Id_Jogador INT,
Id_Jogo INT,
Frame_01 INT,
Frame_02 INT,
Frame_03 INT,
Frame_04 INT,
Frame_05 INT,
Frame_06 INT,
Frame_07 INT,
Frame_O8 INT,
Frame_09 INT,
Frame_10 INT
);Em seguida, iremos inserir os nossos Jogadores.
INSERT INTO dbo.Rodada
(
Id_Jogador,
Id_Jogo
)
SELECT ROW_NUMBER() OVER(ORDER BY nome) AS ID ,1 FROM dbo.Jogador
Agora, para não ser injusto com ninguém , iremos atualizar randomicamente as jogadas de todos os nossos jogadores, para isso, fiz um simples cursor que atualiza cada frame com a função RAND() atualizando randomicamente os valores de 0 a 100.
O Script ficou assim :
DECLARE @ID_JOGADOR INT
DECLARE CUR CURSOR FOR
SELECT ID_Jogador FROM dbo.Rodada
OPEN CUR
FETCH NEXT FROM CUR INTO @ID_JOGADOR
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE RODADA SET Frame_01 = CAST(RAND() * 100 AS INT) ,
Frame_02 = CAST(RAND() * 100 AS INT) ,
Frame_03 = CAST(RAND() * 100 AS INT) ,
Frame_04 = CAST(RAND() * 100 AS INT) ,
Frame_05 = CAST(RAND() * 100 AS INT) ,
Frame_06 = CAST(RAND() * 100 AS INT) ,
Frame_07 = CAST(RAND() * 100 AS INT) ,
Frame_O8 = CAST(RAND() * 100 AS INT) ,
Frame_09 = CAST(RAND() * 100 AS INT) ,
Frame_10 = CAST(RAND() * 100 AS INT)
WHERE Id_Jogador = @id_Jogador
FETCH NEXT FROM CUR INTO @ID_JOGADOR
END
CLOSE CUR
DEALLOCATE CURVamos consultar como ficou o nosso jogo?
SELECT J.nome AS Nome_Jogador,
R.Frame_01,
R.Frame_02,
R.Frame_03,
R.Frame_04,
R.Frame_05,
R.Frame_06,
R.Frame_07,
R.Frame_O8,
R.Frame_09,
R.Frame_10
FROM dbo.Jogador J
INNER JOIN dbo.Rodada R
ON J.ID = R.Id_Jogador;
Poxa, legal!!! Mas qual foi a melhor pontuação de cada jogador? Quem ganhou a rodada?
Primeiro, vamos tentar recuperar a melhor pontuação de cada jogador.
SELECT J.nome AS Nome_Jogador,
MAX(
R.Frame_01,
R.Frame_02,
R.Frame_03,
R.Frame_04,
R.Frame_05,
R.Frame_06,
R.Frame_07,
R.Frame_O8,
R.Frame_09,
R.Frame_10
) AS Melhor_Frame
FROM dbo.Jogador J
INNER JOIN dbo.Rodada R
ON J.ID = R.Id_Jogador;
Eita, deu erro (lembra que falei que o MAX() permite apenas um argumento) ? … É, vamos ter que pensar nisso de um outro jeito…
--GAMBETA
SELECT
J.nome AS Nome_Jogador,
(SELECT MAX(val)
FROM (VALUES (R.Frame_01), (R.Frame_02), (R.Frame_03), (R.Frame_04),
(R.Frame_05), (R.Frame_06), (R.Frame_07), (R.Frame_O8),
(R.Frame_09), (R.Frame_10)) AS value(val)) AS Melhor_Frame
FROM dbo.Jogador J
INNER JOIN dbo.Rodada R ON J.ID = R.Id_Jogador
Hahahaha, viu ai? Gambiarra da pura!!!
Fizemos uma subconsulta com um FROM VALUES, informamos todas as colunas das rodadas e depois atribuímos um alias “val” e depois pedimos para retornar o MAX () desse cara…
É meus amigos… é preciso usar a imaginação. Até o SQL Server 2022, a vida era sofrida…
Agora que vamos demonstrar a função GREATEST(). Lembra que eu falei que ela permite informar várias colunas?
Olha como é bem mais simples :
SELECT J.nome AS Nome_Jogador,
GREATEST(
R.Frame_01,
R.Frame_02,
R.Frame_03,
R.Frame_04,
R.Frame_05,
R.Frame_06,
R.Frame_07,
R.Frame_O8,
R.Frame_09,
R.Frame_10
) AS Melhor_Frame
FROM dbo.Jogador J
INNER JOIN dbo.Rodada R
ON J.ID = R.Id_Jogador;
Bacana não é? isso ajudará bastante os desenvolvedores SQL quando precisar encontrar o maior valor de diversas colunas.
Fizemos um comparativo de performance das duas maneiras apresentadas e não houve muita diferença não, inclusive o exemplo com GREATEST() pareceu ter um plano de execução mais otimizado em relação a nossa gambiarra.

Segue o link da documentação oficial desta logical function.
E aí ?? Quem ganhou o jogo?
Tchan, Tchan, Tchan, Tchan……
SELECT J.Nome,SUM(Frame_01+Frame_02+Frame_03+Frame_04+Frame_05+Frame_06+Frame_07+Frame_O8+Frame_09+Frame_10) AS TOTAL_SCORE
FROM dbo.Jogador J
INNER JOIN dbo.Rodada R ON J.ID = R.Id_Jogador
GROUP BY J.nome
ORDER BY TOTAL_SCORE DESC
Eitaaaaaaaa!!! não costumo ganhar nem uma rifa de frango, mas hoje incrivelmente a sorte estava ao meu favor!!!
Parabéns pra mim.. (Alguns dirão que o resultado foi manipulado, mas não foi não tá?) kkkkk
Por hoje é isso galera, espero que tenham gostado.
Tentarei postar com mais frequência.
Forte abraço, até mais!!
Gustavo Larocca
Consultor SQL server
Gostou do conteúdo?
Acompanhe novos artigos sobre SQL Server, performance e administração de banco de dados.

