sql >> Database >  >> RDS >> Sqlserver

Lopend totaal berekenen met OVER-clausule en PARTITION BY-clausule in SQL Server

Je komt vaak scenario's tegen waarin je een lopend totaal van een hoeveelheid moet berekenen.

Een lopend totaal verwijst naar de som van waarden in alle cellen van een kolom die voorafgaat aan de volgende cel in die bepaalde kolom.

Laten we een voorbeeld bekijken om dit duidelijker te maken.

Zoals je kunt zien, bevat de derde rij van de RunningAgeTotal-kolom de som van alle waarden in de 1 tot de 3 rijen van de StudentAge-kolom, d.w.z. 14 + 12 + 13 =39.

Evenzo is de waarde van de 4 rijen van de RunningAgeTotal-kolom 49, wat de som is van de waarden in de 1 tot de 4 rijen van de StudentAge-kolom.

In de SQL Server kan de OVER-component worden gebruikt om lopende totalen te berekenen.

Laten we eens kijken hoe we dit kunnen gebruiken aan de hand van een voorbeeld hieronder.

Eenvoudig voorbeeld van het berekenen van het lopende SQL-totaal

Laten we wat dummy-gegevens maken voordat we daadwerkelijk een query schrijven die een lopend totaal berekent.

Voer eerst het volgende script uit:

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 )

Dit script maakt de tabel Studenten aan in de School-database. De tabel bevat vier kolommen:Id, StudentName, StudentGender en Student. De INSERT-instructie voegt 10 dummy-records toe aan de database.

Om het lopende totaal van sql te berekenen, moeten we een OVER-clausule gebruiken en de kolom toevoegen waarvoor we het lopende totaal willen berekenen. Het volgende script berekent het lopende totaal van de waarden in de kolom StudentAge en voegt het resultaat toe aan de kolom RunningAgeTotal.

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

In het bovenstaande script haalt de SELECT-instructie de kolommen StudentName, StudentGender en StudentAge op, samen met de kolom met het lopende totaal, d.w.z. RunningAgeTotal. De SUM Aggregate-functie voegt de waarden toe aan de StudentAge-kolom en de OVER-component bepaalt dat de optelling moet worden uitgevoerd in de vorm van een lopend totaal in volgorde van de Id-kolom. De uitvoer van het bovenstaande script is als volgt:

Bereken het lopende gemiddelde van SQL

U kunt het script in de laatste sectie wijzigen om een ​​lopende gemiddelde leeftijd van alle studenten in de tabel Studenten te berekenen. Voer hiervoor het volgende script uit:

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

Zoals je kunt zien, gebruiken we de AVG-aggregatiefunctie om de gemiddelde leeftijd van alle studenten in de kolom StudentLeeftijd te berekenen. De uitvoer van het bovenstaande script ziet er als volgt uit:

Bekijk de derde rij van de kolom RunningAgeAverage. Het bevat het gemiddelde van de waarden van de 1 tot 3 rijen in de kolom StudentAge, d.w.z. (14 + 12 + 13)/3 =13.

Lopend totaal partitioneren op kolomwaarden

U kunt ook een lopend totaal berekenen door gegevens te partitioneren op basis van de waarden in een bepaalde kolom. U kunt bijvoorbeeld een sql-totaal berekenen van de leeftijd van de studenten, gepartitioneerd op geslacht. Om dit te doen, moet u een PARTITION BY-statement gebruiken samen met de OVER-clausule.

Bekijk het volgende voorbeeld:

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

Het enige verschil tussen het berekenen van het lopende totaal voor alle records en het berekenen van het lopende totaal op geslacht is het gebruik van de clausule PARTITION BY StudentGender tussen haakjes na de OVER-clausule. Het bovenstaande script berekent het lopende totaal voor de waarden in de kolom StudentAge, gepartitioneerd door de waarden in de kolom StudentGender. De uitvoer ziet er als volgt uit.

Bekijk nu de eerste vier waarden in de kolom RunningAgeTotal (gemarkeerd door de rode rechthoek). Deze waarden zijn het lopende totaal van de vrouwelijke studenten. Evenzo bevatten de laatste 6 rijen (gemarkeerd door de groene rechthoek) een lopend totaal van de leeftijd voor de mannelijke studenten in de tabel Studenten.

Problemen met OVER wanneer een kolom een ​​dubbele kolom heeft

Er ontstaat een probleem als een kolom met dubbele waarden wordt gebruikt met een OVER-clausule om een ​​lopend totaal te berekenen. Kijk dan eens in de rubriek StudentAge. Elice, Edward en Josh hebben allemaal dezelfde leeftijd, namelijk 12. Op dezelfde manier hebben Liana en Liza ook dezelfde waarden in de StudentAge-kolom, namelijk 10.

Als je een lopend totaal probeert te berekenen door de kolom StudentAge op te geven tussen haakjes na de OVER-clausule, zul je vreemde resultaten zien. Laten we deze query uitvoeren:

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

De uitvoer van de bovenstaande vraag is als volgt:

In de tweede rij van de kolom RunningAgeTotal is de waarde 29. Het moet echter 19 zijn omdat de rijen 1 en 2 van de kolom StudentAge respectievelijk 9 en 10 bevatten. In dit geval, aangezien zowel de 2 als de 3 rijen van de StudentAge-kolom een ​​dubbele waarde bevatten, d.w.z. 10, wordt de waarde voor de 2 rij van de RunningAgeTotal-kolom berekend door 9, 10 en 10 op te tellen. Op dezelfde manier wordt voor de 3 rij van de kolom RunningAgeTotal, de waarde van de tweede rij die 29 is, wordt gebruikt.

Evenzo, als u naar rij 5 van de kolom RunningAgeTotal kijkt, is de waarde 76. Het zou eigenlijk 40 + 12 =52 moeten zijn. Aangezien de 5, 6 en 7 rijen van de kolom StudentAge dubbele waarden hebben, namelijk 12, het lopende totaal wordt berekend door 40 + 12 + 12 + 12 =76 op te tellen. Dit lopende totaal is gebruikt voor de rijen 6 en 7 van de kolom RunningAgeTotal omdat de rijen 6 en 7 van de kolom StudentAge de dubbele waarden bevatten als de rij 5.

Om deze situatie te voorkomen, moet u stoppen met het gebruik van kolommen met dubbele waarden samen met de OVER-component. De kolom Primaire sleutel is altijd een goede keuze om te gebruiken met de clausule OVER, omdat deze alleen unieke waarden bevat.

Lees ook:

Gegevens groeperen met de functies OVER en PARTITION BY

Lessen over het gebruik van OVER en PARTITION BY


  1. Trigger om M-M-relatie af te dwingen

  2. Python verbinding maken met MySQL-database met MySQL-connector en PyMySQL-voorbeeld

  3. Entity Framework-wizard crasht op MySQL

  4. Controleer of kolomtekenreeks in database een subtekenreeks is van een query in sqlite