SQL Server 2022 – Função GREATEST()

DBA e Consultor de Banco de Dados

SQL Server 2022 – Função GREATEST()

Tempo de leitura: 5 minutos

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 BOLICHE

Logo em seguida, utilizaremos nossa base criada :

USE BOLICHE

Agora 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 CUR

Vamos 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.

https://learn.microsoft.com/en-us/sql/t-sql/functions/logical-functions-greatest-transact-sql?view=sql-server-ver16

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

 

 

 

 

 

 

 

 

 

 

Deixe uma resposta

Este site utiliza o Akismet para reduzir spam. Saiba como seus dados em comentários são processados.