Często spotykasz się ze scenariuszami, w których musisz obliczyć bieżącą sumę ilości.
Suma bieżąca odnosi się do sumy wartości we wszystkich komórkach kolumny, która poprzedza następną komórkę w tej konkretnej kolumnie.
Rzućmy okiem na przykład, aby było to jaśniejsze.
Jak widać, trzeci wiersz kolumny RunningAgeTotal zawiera sumę wszystkich wartości w wierszach od 1 do 3 kolumny Wiek Studenta, tj. 14 + 12 + 13 =39.
Podobnie, wartość 4 wiersza kolumny RunningAgeTotal wynosi 49, co jest sumą wartości w wierszach od 1 do 4 kolumny StudentAge.
W SQL Server klauzula OVER może być używana do obliczania bieżących sum.
Przyjrzyjmy się, jak tego użyć, korzystając z poniższego przykładu.
Prosty przykład obliczania sumy uruchomionej SQL
Utwórzmy kilka fikcyjnych danych, zanim faktycznie napiszemy zapytanie, które obliczy sumę bieżącą.
Najpierw wykonaj następujący skrypt:
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 )
Ten skrypt tworzy tabelę Studenci w bazie danych Szkoły. W tabeli znajdują się cztery kolumny:Id, StudentName, StudentGender i Student. Instrukcja INSERT dodaje 10 fikcyjnych rekordów do bazy danych.
Aby obliczyć sumę bieżącą sql, musimy użyć klauzuli OVER i dodać kolumnę, dla której chcemy obliczyć sumę bieżącą. Poniższy skrypt oblicza bieżącą sumę wartości w kolumnie StudentAge i dodaje wynik do kolumny RunningAgeTotal.
USE School
SELECT Id, StudentName, StudentGender, StudentAge,
SUM (StudentAge) OVER (ORDER BY Id) AS RunningAgeTotal
FROM Students
W powyższym skrypcie instrukcja SELECT pobiera kolumny StudentName, StudentGender i StudentAge wraz z kolumną sumy bieżącej, tj. RunningAgeTotal. Funkcja SUM Aggregate dodaje wartości do kolumny StudentAge, a klauzula OVER określa, że dodawanie powinno odbywać się w postaci sumy bieżącej uporządkowanej według kolumny Id. Wynik powyższego skryptu jest następujący:
Oblicz średnią bieżącą SQL
Możesz zmodyfikować skrypt w ostatniej sekcji, aby obliczyć bieżący średni wiek wszystkich uczniów w tabeli Studenci. Aby to zrobić, wykonaj następujący skrypt:
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
Jak widać, używamy funkcji agregującej AVG, aby obliczyć średni wiek wszystkich uczniów w kolumnie StudentAge. Wynik powyższego skryptu wygląda tak:
Spójrz na trzeci wiersz kolumny RunningAgeAverage. Zawiera średnią wartości z 1 do 3 wierszy w kolumnie StudentAge, tj. (14 + 12 + 13)/3 =13.
Partycjonowanie sumy bieżącej według wartości kolumn
Łączną sumę można również obliczyć, dzieląc dane według wartości w określonej kolumnie. Na przykład, możesz obliczyć bieżącą sumę sql wieku uczniów z podziałem na płeć. Aby to zrobić, musisz użyć instrukcji PARTITION BY wraz z klauzulą OVER.
Spójrz na następujący przykład:
USE School
SELECT Id, StudentName, StudentGender, StudentAge,
SUM (StudentAge) OVER (PARTITION BY StudentGender ORDER BY Id) AS RunningAgeTotal
FROM Students
Jedyną różnicą między obliczeniem sumy kroczącej dla wszystkich rekordów a sumą kroczącą według płci jest użycie klauzuli PARTITION BY StudentGender w nawiasie po klauzuli OVER. Powyższy skrypt oblicza sumę bieżącą dla wartości w kolumnie StudentAge, podzieloną na wartości w kolumnie StudentGender. Wynik wygląda tak.
Teraz spójrz na pierwsze cztery wartości w kolumnie RunningAgeTotal (podświetlone czerwonym prostokątem). Te wartości to bieżąca suma uczennic. Podobnie, ostatnie 6 wierszy (podświetlonych zielonym prostokątem) zawiera bieżącą sumę wieku uczniów płci męskiej w tabeli Studenci.
Problemy z OVER, gdy kolumna ma zduplikowaną kolumnę
Problem pojawia się, jeśli kolumna ze zduplikowanymi wartościami jest używana z klauzulą OVER w celu obliczenia sumy bieżącej. Spójrz na kolumnę StudentAge. Elice, Edward i Josh mają ten sam wiek, tj. 12 lat. Podobnie Liana i Liza również mają te same wartości w kolumnie Wiek Studenta, tj. 10.
Jeśli spróbujesz obliczyć sumę bieżącą, określając kolumnę StudentAge w nawiasie po klauzuli OVER, zobaczysz dziwne wyniki. Uruchommy to zapytanie:
USE School
SELECT Id, StudentName, StudentGender, StudentAge,
SUM (StudentAge) OVER (ORDER BY StudentAge) AS RunningAgeTotal
FROM Students
Wynik powyższego zapytania jest następujący:
W drugim wierszu kolumny RunningAgeTotal wartość wynosi 29. Powinna jednak wynosić 19, ponieważ wiersze 1 i 2 kolumny StudentAge zawierają odpowiednio 9 i 10. W takim przypadku, ponieważ zarówno 2, jak i 3 wiersze kolumny StudentAge zawierają zduplikowaną wartość, tj. 10, wartość 2 wiersza kolumny RunningAgeTotal jest obliczana przez dodanie 9, 10 i 10. Podobnie dla 3 wiersza kolumny RunningAgeTotal kolumna RunningAgeTotal, używana jest wartość z drugiego wiersza, czyli 29.
Podobnie, jeśli spojrzysz na 5 wiersz kolumny RunningAgeTotal, wartość to 76. W rzeczywistości powinno to być 40 + 12 =52. Jednak ponieważ 5, 6 i 7 wierszy kolumny StudentAge mają zduplikowane wartości, tj. 12, suma bieżąca jest obliczana przez dodanie 40 + 12 + 12 + 12 =76. Ta suma bieżąca została użyta w wierszach 6 i 7 kolumny RunningAgeTotal, ponieważ wiersze 6 i 7 kolumny StudentAge zawierają zduplikowane wartości jako wiersz 5.
Aby uniknąć tej sytuacji, musisz przestać używać kolumn ze zduplikowanymi wartościami wraz z klauzulą OVER. Kolumna klucza podstawowego jest zawsze dobrym wyborem do użycia z klauzulą OVER, ponieważ zawiera tylko unikalne wartości.
Przeczytaj również:
Grupowanie danych za pomocą funkcji OVER i PARTITION BY
Lekcje na temat korzystania z funkcji OVER i PARTITION BY