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)…
1 | CREATE DATABASE BOLICHE |
Logo em seguida, utilizaremos nossa base criada :
1 | USE BOLICHE |
Agora iremos criar uma tabela com os Jogadores do nosso Jogo :
1 2 3 4 5 6 7 | 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 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | 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).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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.
1 2 3 4 5 6 | 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 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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…
1 2 3 4 5 6 7 8 9 10 | --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 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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……
1 2 3 4 5 | 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