В SQL, AVG()
функцията е агрегатна функция, която връща средната стойност на всички стойности в даден израз.
Може също да се използва за връщане на средната стойност на всички различни (уникални) стойности в израз.
Изразът трябва да е числов (не може да бъде низ от знаци, битов низ или дата и час).
По-долу са дадени няколко основни примера, за да демонстрирате как работи.
Примерна таблица
Да предположим, че имаме следната таблица:
SELECT * FROM Products;
Резултат:
+------------+------------+------------------- --------------+----------------+----------------- -----------------------+| ProductId | VendorId | Име на продукта | Цена на продукта | Описание на продукта ||-------------+------------+------------------- -------------+----------------+------------------- ---------------------|| 1 | 1001 | Отвертка с лява ръка | 25,99 | Лилаво. Включва кутия за лява ръка. || 2 | 1001 | Дълго тегло (синьо) | 14,75 | Включва дълго чакане. || 3 | 1001 | Дълго тегло (зелено) | 11,99 | Приблизителен период на изчакване от 30 минути. || 4 | 1002 | Малка чук | 33,49 | Дървена дръжка. Безплатни чаши за вино. || 5 | 1003 | Верижен трион | 245,00 | оранжево. Включва резервни пръсти. || 6 | 1003 | Кутия за сламени кучета | NULL | Завързани с лози. Много може да се дъвче. || 7 | 1004 | Чаши за кафе без дъно (4 пакета) | 9,99 | Кафява керамика с масивна дръжка. || 8 | 1001 | Отвертка с дясна ръка | 25,99 | Син. Включва кутия за дясна ръка. |+------------+------------+--------------------- ------------+----------------+------------------- ---------------------+
Пример
Можем да използваме следната заявка, за да получим средната стойност на всички цени.
SELECT AVG(ProductPrice)
FROM Products;
Резултат:
+-------------------+| (Без име на колона) ||-------------------|| 52.457142 |+--------------------+
В този случай информацията за цената се съхранява в ProductPrice
колона и затова предаваме това като аргумент на AVG()
функция, която след това изчислява средната стойност и връща резултата.
Използване на псевдоними на колони
Ще забележите, че предишните резултати не включват име на колона. Това може да се очаква, тъй като AVG()
функцията не връща никакви колони. Можете лесно да предоставите име на колона, като зададете псевдоним.
SELECT AVG(ProductPrice) AS Average
FROM Products;
Резултат:
+-----------+| Средно ||-----------|| 52.457142 |+----------+
Филтрирани резултати
AVG()
функцията работи с редовете, върнати от заявката. Така че, ако филтрирате резултатите, резултатът от AVG()
ще отрази това.
SELECT AVG(ProductPrice) AS Average
FROM Products
WHERE VendorId = 1001;
Резултат:
+-----------+| Средно ||-----------|| 19,680000 |+----------+
В този случай 19,680000 е средната цена на всички продукти, предлагани от посочения доставчик.
NULL
Стойности
AVG()
функцията игнорира всеки NULL
стойности. В нашата примерна таблица по-горе продуктов номер 6
има NULL
в неговия ProductPrice
колона, но това беше игнорирано в нашия AVG()
пример.
В зависимост от вашата СУБД и настройките ви може или не може да видите предупреждение, че NULL
стойностите бяха елиминирани в набора от резултати.
Ето пример за това, което може да видите:
SELECT AVG(ProductPrice) AS Average
FROM Products;
Резултат:
+-----------+| Средно ||-----------|| 52.457142 |+-----------+Предупреждение:Нулевата стойност се елиминира чрез агрегат или друга операция SET.
Всичко това ни казва, че колоната съдържа поне един NULL
стойност и че е била игнорирана при изчисляване на резултатите.
Данни за дата/час
AVG()
функцията не приема изрази за дата/час.
Да предположим, че имаме следната таблица:
SELECT PetName, DOB
FROM Pets;
Резултат:
+-----------+------------+| Име на домашни любимци | DOB ||-----------+------------|| Пухкави | 20.11.2020 || Извличане | 2019-08-16 || Надраскване | 2018-10-01 || Размахване | 2020-03-15 || Tweet | 28.11.2020 || Пухкави | 17.09.2020 || Кора | NULL || Мяу | NULL |+-----------+------------+
Ако се опитаме да използваме AVG()
на DOB
колона, ще получим грешка.
SELECT AVG(DOB) AS Average
FROM Pets;
Резултат:
Съобщение 8117, ниво 16, състояние 1, ред 1 Датата на тип данни на операнда е невалидна за оператора avg.
Данни за знаци
AVG()
функцията също не приема изрази за низ от символи.
Ето какво се случва, ако се опитаме да използваме AVG()
на ProductName
колона на нашите Products
таблица (която използва тип данни varchar):
SELECT AVG(ProductName) AS Average
FROM Products;
Резултат:
Съобщение 8117, ниво 16, състояние 1, ред 1 Операнд тип данни varchar е невалиден за оператор avg.
DISTINCT
Ключова дума
Можете да използвате DISTINCT
ключова дума с AVG()
за изчисляване само на различни стойности. Тоест, ако има дублиращи се стойности, те се третират като една стойност.
Пример:
SELECT AVG(DISTINCT ProductPrice) AS DistinctAverage
FROM Products;
Резултат:
+------------------+| DisstinctAverage ||------------------|| 56.868333 |+-------------------+
Можем да видим, че този резултат е по-висок от резултата, който получихме без DISTINCT
ключова дума.
За да обобщим, получихме 52,457142 без DISTINCT
ключова дума и 56.868333 с DISTINCT
ключова дума.
Това е така, защото има два артикула, които споделят една и съща цена (отвертката с лява ръка и отвертката с дясна ръка са на цена 25,99). Следователно, AVG()
функция, когато се използва с DISTINCT
ключова дума, третира и двете стойности като една и съответно изчислява резултата си.
Функции на прозореца
В зависимост от вашата СУБД, може да сте в състояние да използвате OVER
клауза с вашия AVG()
функция за създаване на прозоречна функция.
Прозоречната функция изпълнява агрегатно-подобна операция върху набор от редове на заявка. Той произвежда резултат за всеки ред на заявката. Това е в контраст с агрегирана операция, която групира редовете на заявката в един ред с резултати.
Ето пример за демонстриране на концепцията.
Вече видяхме Products
маса. Нашата база данни също има Customers
таблица и съдържа следните данни:
+--------------+---------------------+-------- -----------+------------+----------------+------- -----+----------+----------------+| Идентификатор на клиента | Име на клиента | Пощенски адрес | Град | щатска провинция | Пощенски код | Държава | Телефон ||--------------+---------------------+-------- ----------+-----------+----------------+-------- ----+----------+----------------+| 1001 | Палмово килерче | 20 Еспланада | Таунсвил | QLD | 2040 г. | AUS | (308) 555-0100 || 1002 | Висок мак | Главен път 12 | Колумб | OH | 43333 | САЩ | (310) 657-0134 || 1003 | луди същества | 10 безкрайни цикъла | Кернс | QLD | 4870 | AUS | (418) 555-0143 || 1004 | Опа медия | 4 Beachside Drive | Пърт | WA | 1234 | AUS | (405) 443-5987 || 1005 | Strange Names Inc. | Улица Джордж 789 | Сидни | NSW | 2000 | AUD | (318) 777-0177 || 1006 | Hi-Five Solutionists | 5 High Street | Highlands | Здрасти | 1254 | AUS | (415) 413-5182 |+--------------+---------------------+---- ---------------+-----------+----------------+--- ---------+----------+----------------+
Можем да извлечем данни от тези таблици и да ги представим като един набор от резултати, като използваме присъединяване.
Можем също да използваме AVG()
функция с OVER
клауза за прилагане на прозоречна функция към данните.
SELECT
v.VendorName,
p.ProductName,
p.ProductPrice,
AVG(ProductPrice) OVER (PARTITION BY v.VendorName) AS "Average For This Vendor"
FROM Products p
INNER JOIN Vendors v
ON v.VendorId = p.VendorId
ORDER BY VendorName, ProductPrice, "Average For This Vendor";
Резултат:
+---------------+------------------------------ ---+----------------+--------------------------+| Име на доставчик | Име на продукта | Цена на продукта | Средно за този доставчик ||--------------+---------------------------- -----+----------------+----------------------------------- || Котенца Кати | Чаши за кафе без дъно (4 пакета) | 9,99 | 9,990000 || Консумативи за Марс | Дълго тегло (зелено) | 11,99 | 19,680000 || Консумативи за Марс | Дълго тегло (синьо) | 14,75 | 19,680000 || Консумативи за Марс | Отвертка с дясна ръка | 25,99 | 19,680000 || Консумативи за Марс | Отвертка с лява ръка | 25,99 | 19,680000 || Медали с педали | Кутия за сламени кучета | NULL | 245,000000 || Медали с педали | Верижен трион | 245,00 | 245,000000 || Ранди Рууферс | Чук | 33,49 | 33,490000 |+--------------+------------------------------ --+----------------+-------------------------+предварително>В този случай използвахме
OVER
клауза с нашияAVG()
функция за разделяне на резултата по име на доставчик.По този начин успяхме да върнем информация за цените за всеки продукт, както и средната цена на всички продукти от този доставчик. Средната цена се променя с промяната на доставчика (освен ако няколко доставчици имат една и съща средна стойност), но остава една и съща за всички продукти от един и същ доставчик.
Тази концепция може да се приложи и към други агрегатни функции в SQL, като
SUM()
,MIN()
,MAX()
иCOUNT()
.