sql >> Database teknologi >  >> RDS >> Sqlserver

Beregning af løbende total med OVER-klausul og PARTITION BY-klausul i SQL Server

Du støder ofte på scenarier, hvor du skal beregne en løbende sum af en mængde.

En løbende total refererer til summen af ​​værdier i alle celler i en kolonne, der går forud for den næste celle i den pågældende kolonne.

Lad os tage et kig på et eksempel for at gøre dette klarere.

Som du kan se, indeholder den tredje række i kolonnen RunningAgeTotal summen af ​​alle værdierne i 1 til de 3 rækker i kolonnen StudentAge, dvs. 14 + 12 + 13 =39.

På samme måde er værdien af ​​de 4 rækker i kolonnen RunningAgeTotal 49, hvilket er summen af ​​værdierne i 1 til 4 rækkerne i kolonnen StudentAge.

I SQL Server kan OVER-sætningen bruges til at beregne løbende totaler.

Lad os undersøge, hvordan du bruger dette ved hjælp af et eksempel nedenfor.

Simpelt eksempel på beregning af SQL Running Total

Lad os oprette nogle dummy-data, før vi rent faktisk skriver en forespørgsel, der beregner en løbende total.

Først skal du udføre følgende 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 )

Dette script opretter tabellen Elever i skolens database. Der er fire kolonner i tabellen:Id, StudentName, StudentGender og Student. INSERT-sætningen tilføjer 10 dummy-poster til databasen.

For at beregne sql's løbende total, skal vi bruge en OVER-klausul og tilføje den kolonne, som vi ønsker at beregne den løbende total for. Følgende script beregner den løbende sum af værdierne i kolonnen StudentAge og føjer resultatet til kolonnen RunningAgeTotal.

USE School
SELECT Id, StudentName, StudentGender, StudentAge,
SUM (StudentAge) OVER (ORDER BY Id) AS RunningAgeTotal
FROM Students

I scriptet ovenfor henter SELECT-sætningen StudentName-, StudentGender- og StudentAge-kolonnerne sammen med den løbende total-kolonne, dvs. RunningAgeTotal. Funktionen SUM Aggregate tilføjer værdierne til kolonnen StudentAge, og OVER-sætningen bestemmer, at tilføjelsen skal udføres i form af løbende total sorteret efter Id-kolonnen. Outputtet af ovenstående script er som følger:

Beregn SQL-gennemsnit

Du kan ændre scriptet i det sidste afsnit for at beregne en løbende gennemsnitsalder for alle eleverne i Elevtabellen. For at gøre dette skal du udføre følgende 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

Som du kan se, bruger vi AVG-aggregatfunktionen til at beregne gennemsnitsalderen for alle eleverne i kolonnen StudentAge. Outputtet af ovenstående script ser sådan ud:

Tag et kig på den tredje række i kolonnen RunningAgeAverage. Den indeholder gennemsnittet af værdierne for de 1 til 3 rækker i kolonnen StudentAge, dvs. (14 + 12 + 13)/3 =13.

Partitionering af løbende total efter kolonneværdier

Du kan også beregne en løbende total ved at partitionere data efter værdierne i en bestemt kolonne. For eksempel kan du beregne en kørende sql-total af elevernes alder, opdelt efter køn. For at gøre dette skal du bruge en PARTITION BY-sætning sammen med OVER-sætningen.

Tag et kig på følgende eksempel:

USE School
SELECT Id, StudentName, StudentGender, StudentAge,
SUM (StudentAge) OVER (PARTITION BY StudentGender ORDER BY Id) AS RunningAgeTotal
FROM Students

Den eneste forskel mellem at beregne den løbende total for alle poster og at beregne den løbende total efter køn er brugen af ​​PARTITION BY StudentGender-klausulen i parentesen efter OVER-klausulen. Ovenstående script beregner den løbende total for værdierne i kolonnen StudentAge, opdelt efter værdierne i kolonnen StudentKøn. Outputtet ser sådan ud.

Tag nu et kig på de første fire værdier i kolonnen RunningAgeTotal (fremhævet af det røde rektangel). Disse værdier er den løbende sum af de kvindelige studerende. På samme måde indeholder de sidste 6 rækker (fremhævet af det grønne rektangel) en løbende total af alderen for de mandlige elever i Elevtabellen.

Problemer med OVER, når en kolonne har en dubletkolonne

Et problem opstår, hvis en kolonne med duplikerede værdier bruges med et OVER-udtryk for at beregne en løbende total. Tag et kig på kolonnen StudentAge. Elice, Edward og Josh har alle samme alder, dvs. 12. På samme måde har Liana og Liza også de samme værdier i kolonnen StudentAge, dvs. 10.

Hvis du forsøger at beregne en løbende total ved at angive kolonnen StudentAge i parentesen efter OVER-sætningen, vil du se nogle mærkelige resultater. Lad os køre denne forespørgsel:

USE School
SELECT Id, StudentName, StudentGender, StudentAge,
SUM (StudentAge) OVER (ORDER BY StudentAge) AS RunningAgeTotal
FROM Students

Outputtet af ovenstående forespørgsel er som følger:

I anden række i kolonnen RunningAgeTotal er værdien 29. Den skal dog være 19, fordi rækkerne 1 og 2 i kolonnen StudentAge indeholder henholdsvis 9 og 10. I dette tilfælde, da både 2 og 3 rækker i kolonnen StudentAge indeholder en duplikeret værdi, dvs. 10, beregnes værdien for rækken 2 i kolonnen RunningAgeTotal ved at tilføje 9, 10 og 10. På samme måde, for 3 rækken af kolonnen RunningAgeTotal, bruges værdien fra den anden række, der er 29.

Ligeledes, hvis du ser på rækken 5 i kolonnen RunningAgeTotal, er værdien 76. Den burde faktisk være 40 + 12 =52. Men da rækkerne 5, 6 og 7 i kolonnen StudentAge har duplikerede værdier, dvs. 12, den løbende total beregnes ved at tilføje 40 + 12 + 12 + 12 =76. Denne løbende total er blevet brugt til rækkerne 6 og 7 i kolonnen RunningAgeTotal, fordi rækkerne 6 og 7 i kolonnen StudentAlder indeholder de duplikerede værdier som rækken 5.

For at undgå denne situation skal du stoppe med at bruge kolonner med duplikerede værdier sammen med OVER-sætningen. Primærnøglekolonnen er altid et godt valg til brug med OVER-sætningen, da den kun indeholder unikke værdier.

Læs også:

Gruppering af data ved hjælp af OVER- og PARTITION BY-funktionerne

Lektioner om brug af OVER og PARTITION BY


  1. MySQL få rækkeposition i BESTIL EFTER

  2. CAST vs ssis dataflow implicit konverteringsforskel

  3. Opdel given streng og forbered sagsfremstilling

  4. Entity Framework kerne - Indeholder er der forskel på store og små bogstaver eller ufølsom?