Muitas vezes você se depara com cenários em que precisa calcular um total de uma quantidade.
Um total em execução refere-se à soma de valores em todas as células de uma coluna que precede a próxima célula dessa coluna específica.
Vamos dar uma olhada em um exemplo para tornar isso mais claro.
Como você pode ver, a terceira linha da coluna RunningAgeTotal contém a soma de todos os valores nas linhas 1 a 3 da coluna StudentAge, ou seja, 14 + 12 + 13 =39.
Da mesma forma, o valor da 4 linha da coluna RunningAgeTotal é 49, que é a soma dos valores de 1 a 4 linhas da coluna StudentAge.
No SQL Server, a cláusula OVER pode ser usada para calcular os totais em execução.
Vamos explorar como usar isso com a ajuda de um exemplo abaixo.
Exemplo simples de cálculo do total de execução do SQL
Vamos criar alguns dados fictícios antes de realmente escrever uma consulta que calcula um total em execução.
Primeiro, execute o seguinte script:
CREATE DATABASE School
GO
USE School
GO
CREATE TABLE Students
(
Id INT PRIMARY KEY IDENTITY,
StudentName VARCHAR (50),
StudentGender VARCHAR (50),
StudentAge INT
)
GO
INSERT INTO Students VALUES ('Sally', 'Female', 14 )
INSERT INTO Students VALUES ('Edward', 'Male', 12 )
INSERT INTO Students VALUES ('Jon', 'Male', 13 )
INSERT INTO Students VALUES ('Liana', 'Female', 10 )
INSERT INTO Students VALUES ('Ben', 'Male', 11 )
INSERT INTO Students VALUES ('Elice', 'Female', 12 )
INSERT INTO Students VALUES ('Nick', 'Male', 9 )
INSERT INTO Students VALUES ('Josh', 'Male', 12 )
INSERT INTO Students VALUES ('Liza', 'Female', 10 )
INSERT INTO Students VALUES ('Wick', 'Male', 15 )
Este script cria a tabela Alunos dentro do banco de dados Escola. Há quatro colunas na tabela:Id, StudentName, StudentGender e Student. A instrução INSERT adiciona 10 registros fictícios ao banco de dados.
Para calcular o total de execução do sql, temos que usar uma cláusula OVER e adicionar a coluna para a qual queremos calcular o total de execução. O script a seguir calcula o total acumulado dos valores na coluna StudentAge e adiciona o resultado à coluna RunningAgeTotal.
USE School
SELECT Id, StudentName, StudentGender, StudentAge,
SUM (StudentAge) OVER (ORDER BY Id) AS RunningAgeTotal
FROM Students
No script acima, a instrução SELECT recupera as colunas StudentName, StudentGender e StudentAge junto com a coluna total em execução, ou seja, RunningAgeTotal. A função SUM Aggregate adiciona os valores à coluna StudentAge e a cláusula OVER determina que a adição deve ser executada na forma de execução total ordenada pela coluna Id. A saída do script acima é a seguinte:
Calcular média de execução do SQL
Você pode modificar o script na última seção para calcular uma média de idade de todos os alunos na tabela Alunos. Para isso, execute o seguinte script:
USE School
SELECT Id, StudentName, StudentGender, StudentAge,
SUM (StudentAge) OVER (ORDER BY Id) AS RunningAgeTotal,
AVG (StudentAge) OVER (ORDER BY Id) AS RunningAgeAverage
FROM Students
Como você pode ver, usamos a função agregada AVG para calcular a idade média de todos os alunos na coluna StudentAge. A saída do script acima é assim:
Dê uma olhada na terceira linha da coluna RunningAgeAverage. Ele contém a média dos valores de 1 a 3 linhas na coluna StudentAge, ou seja (14 + 12 + 13)/3 =13.
Particionando o total de execução por valores de coluna
Você também pode calcular um total em execução particionando os dados pelos valores em uma coluna específica. Por exemplo, você pode calcular um total de execução sql da idade dos alunos, divididos por sexo. Para fazer isso, você precisa usar uma instrução PARTITION BY junto com a cláusula OVER.
Dê uma olhada no exemplo a seguir:
USE School
SELECT Id, StudentName, StudentGender, StudentAge,
SUM (StudentAge) OVER (PARTITION BY StudentGender ORDER BY Id) AS RunningAgeTotal
FROM Students
A única diferença entre calcular o total de corrida para todos os registros e calcular o total de corrida por gênero é o uso da cláusula PARTITION BY StudentGender dentro do parêntese após a cláusula OVER. O script acima calcula o total em execução para os valores na coluna StudentAge, particionado pelos valores na coluna StudentGender. A saída se parece com isso.
Agora, dê uma olhada nos primeiros quatro valores na coluna RunningAgeTotal (destacado pelo retângulo vermelho). Esses valores são o total acumulado das alunas. Da mesma forma, as últimas 6 linhas (destacadas pelo retângulo verde) contêm um total acumulado da idade dos alunos do sexo masculino na tabela Alunos.
Problemas com OVER quando uma coluna tem uma coluna duplicada
Um problema surge se uma coluna com valores duplicados for usada com uma cláusula OVER para calcular um total em execução. Dê uma olhada na coluna StudentAge. Elice, Edward e Josh têm a mesma idade, ou seja, 12. Da mesma forma, Liana e Liza também têm os mesmos valores na coluna StudentAge, ou seja, 10.
Se você tentar calcular um total em execução especificando a coluna StudentAge dentro dos parênteses após a cláusula OVER, verá alguns resultados estranhos. Vamos executar esta consulta:
USE School
SELECT Id, StudentName, StudentGender, StudentAge,
SUM (StudentAge) OVER (ORDER BY StudentAge) AS RunningAgeTotal
FROM Students
A saída da consulta acima é a seguinte:
Na segunda linha da coluna RunningAgeTotal, o valor é 29. No entanto, deve ser 19 porque as linhas 1 e 2 da coluna StudentAge contêm 9 e 10, respectivamente. Neste caso, uma vez que 2 e 3 linhas da coluna StudentAge contêm um valor duplicado, ou seja, 10, o valor da 2ª linha da coluna RunningAgeTotal é calculado adicionando 9, 10 e 10. Da mesma forma, para a 3ª linha de a coluna RunningAgeTotal, o valor da segunda linha que é 29 é usado.
Da mesma forma, se você observar a linha 5 da coluna RunningAgeTotal, o valor é 76. Na verdade, deve ser 40 + 12 =52. No entanto, como as linhas 5, 6 e 7 da coluna StudentAge têm valores duplicados, ou seja, 12, o total em execução é calculado adicionando 40 + 12 + 12 + 12 =76. Este total em execução foi usado para as linhas 6 e 7 da coluna RunningAgeTotal porque as linhas 6 e 7 da coluna StudentAge contêm os valores duplicados como a linha 5.
Para evitar essa situação, você precisa parar de usar colunas com valores duplicados junto com a cláusula OVER. A coluna Chave Primária é sempre uma boa opção para ser usada com a cláusula OVER, pois contém apenas valores exclusivos.
Leia também:
Agrupando dados usando as funções OVER e PARTITION BY
Lições sobre como usar OVER e PARTITION BY