Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Изчисляване на текущото общо с клауза OVER и клауза PARTITION BY в SQL Server

Често се натъквате на сценарии, при които трябва да изчислите общо количество.

Текущата сума се отнася до сумата от стойности във всички клетки на колона, която предхожда следващата клетка в тази конкретна колона.

Нека да разгледаме пример, за да направим това по-ясно.

Както можете да видите, третият ред на колоната RunningAgeTotal съдържа сумата от всички стойности от 1 до 3 реда на колоната StudentAge, т.е. 14 + 12 + 13 =39.

По същия начин стойността на 4-тия ред на колоната RunningAgeTotal е 49, което е сумата от стойностите от 1 до 4 реда на колоната StudentAge.

В SQL Server клаузата OVER може да се използва за изчисляване на текущи суми.

Нека разгледаме как да използваме това с помощта на пример по-долу.

Прост пример за изчисляване на общия обем на изпълнение на SQL

Нека създадем някои фиктивни данни, преди всъщност да напишем заявка, която изчислява текущата сума.

Първо, изпълнете следния скрипт:

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 )

Този скрипт създава таблицата Students в училищната база данни. В таблицата има четири колони:Id, StudentName, StudentGender и Student. Инструкцията INSERT добавя 10 фиктивни записа към базата данни.

За да изчислим текущата сума на sql, трябва да използваме клауза OVER и да добавим колоната, за която искаме да изчислим текущата сума. Следният скрипт изчислява текущата сума на стойностите в колоната StudentAge и добавя резултата към колоната RunningAgeTotal.

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

В скрипта по-горе операторът SELECT извлича колоните StudentName, StudentGender и StudentAge заедно с текущата колона, т.е. RunningAgeTotal. Функцията SUM Aggregate добавя стойностите към колоната StudentAge и клаузата OVER определя, че добавянето трябва да се извърши под формата на текущо общо, подредено от колоната Id. Резултатът от горния скрипт е както следва:

Изчислете текущата средна стойност на SQL

Можете да промените скрипта в последния раздел, за да изчислите текущата средна възраст на всички ученици в таблицата Студенти. За да направите това, изпълнете следния скрипт:

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

Както можете да видите, ние използваме обобщената функция AVG, за да изчислим средната възраст на всички ученици в колоната StudentAge. Резултатът от горния скрипт изглежда така:

Обърнете внимание на третия ред на колоната RunningAgeAverage. Той съдържа средните стойности на 1 до 3 реда в колоната StudentAge, т.е. (14 + 12 + 13)/3 =13.

Разделяне на текущата сума по стойности на колони

Можете също да изчислите текущата сума, като разделите данните по стойностите в определена колона. Например, можете да изчислите общата сума на sql от възрастта на учениците, разделена по пол. За да направите това, трябва да използвате оператор PARTITION BY заедно с клаузата OVER.

Разгледайте следния пример:

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

Единствената разлика между изчисляването на текущия сбор за всички записи и изчисляването на текущия сбор по пол е използването на клаузата PARTITION BY StudentGender в скобите след клаузата OVER. Горният скрипт изчислява текущата сума за стойностите в колоната StudentAge, разделена на стойностите в колоната StudentGender. Резултатът изглежда така.

Сега разгледайте първите четири стойности в колоната RunningAgeTotal (откроена от червения правоъгълник). Тези стойности са общият сбор на студентките. По същия начин последните 6 реда (маркирани със зеления правоъгълник) съдържат текуща обща възраст за учениците от мъжки пол в таблицата за ученици.

Проблеми с OVER, когато колона има дублирана колона

Проблем възниква, ако колона с дублиращи се стойности се използва с клауза OVER, за да се изчисли текущата сума. Разгледайте колоната StudentAge. Елис, Едуард и Джош имат една и съща възраст, т.е. 12. По същия начин Лиана и Лиза също имат едни и същи стойности в колоната StudentAge, т.е. 10.

Ако се опитате да изчислите текущата сума, като посочите колоната StudentAge в скобите след клаузата OVER, ще видите някои странни резултати. Нека изпълним тази заявка:

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

Резултатът от горната заявка е както следва:

Във втория ред на колоната RunningAgeTotal стойността е 29. Въпреки това, тя трябва да бъде 19, тъй като 1 и 2 ред на колоната StudentAge съдържат съответно 9 и 10. В този случай, тъй като и 2, и 3 реда от колоната StudentAge съдържат дублирана стойност, т.е. 10, стойността за втория ред на колоната RunningAgeTotal се изчислява чрез добавяне на 9, 10 и 10. По същия начин, за 3 ред от колоната RunningAgeTotal се използва стойността от втория ред, която е 29.

По същия начин, ако погледнете 5-ия ред на колоната RunningAgeTotal, стойността е 76. Тя всъщност трябва да бъде 40 + 12 =52. Въпреки това, тъй като 5, 6 и 7 ред на колоната StudentAge имат дублиращи се стойности, т.е. 12, текущата сума се изчислява чрез добавяне на 40 + 12 + 12 + 12 =76. Тази текуща сума е била използвана за редове 6 и 7 на колоната RunningAgeTotal, тъй като редовете 6 и 7 на колоната StudentAge съдържат дублиращите се стойности като ред 5.

За да избегнете тази ситуация, трябва да спрете да използвате колони с дублиращи се стойности заедно с клаузата OVER. Колоната Първичен ключ винаги е добър избор за използване с клаузата OVER, тъй като съдържа само уникални стойности.

Прочетете също:

Групиране на данни с помощта на функциите OVER и PARTITION BY

Уроци за използване на OVER и PARTITION BY


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL Server - вътрешно присъединяване при актуализиране

  2. Как работи FOR XML PATH('') при конкатенация на редове

  3. Еквивалентът на SQL Server на Sleep():Инструкцията WAITFOR

  4. Използване на транзакция ROLLBACK в SQL Server

  5. Изберете топ 10 записа за всяка категория