В SQL, GROUP BY
клаузата може да се използва за разделяне на резултатите от заявка на групи от редове.
Това обикновено се прави, за да се извърши едно или повече агрегиране на всяка група.
Пример 1
Ето пример за демонстрация на GROUP BY
клауза.
Вземете следната таблица:
SELECT * FROM Products;
Резултат:
+-------------+------------+---------------------------------+----------------+-----------------------------------------+ | ProductId | VendorId | ProductName | ProductPrice | ProductDescription | |-------------+------------+---------------------------------+----------------+-----------------------------------------| | 1 | 1001 | Left handed screwdriver | 25.99 | Purple. Includes left handed carry box. | | 2 | 1001 | Long Weight (blue) | 14.75 | Includes a long wait. | | 3 | 1001 | Long Weight (green) | 11.99 | Approximate 30 minute waiting period. | | 4 | 1002 | Sledge Hammer | 33.49 | Wooden handle. Free wine glasses. | | 5 | 1003 | Chainsaw | 245.00 | Orange. Includes spare fingers. | | 6 | 1003 | Straw Dog Box | 55.99 | Tied with vines. Very chewable. | | 7 | 1004 | Bottomless Coffee Mugs (4 Pack) | 9.99 | Brown ceramic with solid handle. | +-------------+------------+---------------------------------+----------------+-----------------------------------------+
Можем да изпълним следната заявка към тази таблица.
SELECT
VendorId,
COUNT(VendorId) AS Count
FROM Products
GROUP BY VendorId;
Резултат:
+------------+---------+ | VendorId | Count | |------------+---------| | 1001 | 3 | | 1002 | 1 | | 1003 | 2 | | 1004 | 1 | +------------+---------+
Тук използваме COUNT()
агрегатна функция за връщане на броя на редовете за всеки VendorId
, след това GROUP BY
клауза за групиране на резултатите.
Пример 2
В този пример използваме SUM()
aggregate функция, за да върне общото население на всички градове в даден район, след това GROUP BY
клауза за групиране на резултатите.
Представете си, че имаме таблица, наречена City
който съхранява имената на градовете и тяхното население, както и съответните им кодове на държави и области (в отделни колони).
Като това:
SELECT * FROM city
WHERE CountryCode IN ('AGO', 'ARE', 'AUS');
Резултат:
+------+---------------+---------------+-----------------+--------------+ | ID | Name | CountryCode | District | Population | |------+---------------+---------------+-----------------+--------------| | 56 | Luanda | AGO | Luanda | 2022000 | | 57 | Huambo | AGO | Huambo | 163100 | | 58 | Lobito | AGO | Benguela | 130000 | | 59 | Benguela | AGO | Benguela | 128300 | | 60 | Namibe | AGO | Namibe | 118200 | | 64 | Dubai | ARE | Dubai | 669181 | | 65 | Abu Dhabi | ARE | Abu Dhabi | 398695 | | 66 | Sharja | ARE | Sharja | 320095 | | 67 | al-Ayn | ARE | Abu Dhabi | 225970 | | 68 | Ajman | ARE | Ajman | 114395 | | 130 | Sydney | AUS | New South Wales | 3276207 | | 131 | Melbourne | AUS | Victoria | 2865329 | | 132 | Brisbane | AUS | Queensland | 1291117 | | 133 | Perth | AUS | West Australia | 1096829 | | 134 | Adelaide | AUS | South Australia | 978100 | | 135 | Canberra | AUS | Capital Region | 322723 | | 136 | Gold Coast | AUS | Queensland | 311932 | | 137 | Newcastle | AUS | New South Wales | 270324 | | 138 | Central Coast | AUS | New South Wales | 227657 | | 139 | Wollongong | AUS | New South Wales | 219761 | | 140 | Hobart | AUS | Tasmania | 126118 | | 141 | Geelong | AUS | Victoria | 125382 | | 142 | Townsville | AUS | Queensland | 109914 | | 143 | Cairns | AUS | Queensland | 92273 | +------+---------------+---------------+-----------------+--------------+
Намалих резултатите до само три държави, в противен случай списъкът щеше да е наличен твърде дълго за тази статия.
Да предположим, че искаме да получим населението на всеки окръг и искаме да изброим всеки район, заедно с населението и кода на държавата.
Бихме могли да направим това.
SELECT
CountryCode,
District,
SUM(Population) AS Population
FROM City
WHERE CountryCode IN ('AGO', 'ARE', 'AUS')
GROUP BY CountryCode, District
ORDER BY CountryCode;
Резултат:
+---------------+-----------------+--------------+ | CountryCode | District | Population | |---------------+-----------------+--------------| | AGO | Benguela | 258300 | | AGO | Huambo | 163100 | | AGO | Luanda | 2022000 | | AGO | Namibe | 118200 | | ARE | Abu Dhabi | 624665 | | ARE | Ajman | 114395 | | ARE | Dubai | 669181 | | ARE | Sharja | 320095 | | AUS | Capital Region | 322723 | | AUS | New South Wales | 3993949 | | AUS | Queensland | 1805236 | | AUS | South Australia | 978100 | | AUS | Tasmania | 126118 | | AUS | Victoria | 2990711 | | AUS | West Australia | 1096829 | +---------------+-----------------+--------------+
Можем да видим, че нашите резултати са групирани, както е посочено, и сега получаваме пълното население за всеки район (за разлика от населението на отделните градове, което е начинът, по който те се съхраняват в основната таблица).
Обърнете внимание, че GROUP BY
клаузата трябва да идва след всяко WHERE
клауза и преди всяко ORDER BY
клауза.
Ако искаме да получим населението на всяка държава вместо на областта, нашата заявка става още по-компактна.
SELECT
CountryCode,
SUM(Population) AS Population
FROM City
WHERE CountryCode IN ('AGO', 'ARE', 'AUS')
GROUP BY CountryCode
ORDER BY CountryCode;
Резултат:
+---------------+--------------+ | CountryCode | Population | |---------------+--------------| | AGO | 2561600 | | ARE | 1728336 | | AUS | 11313666 | +---------------+--------------+
Имайте предвид, че тази конкретна примерна база данни е много остаряла и нейните популации не отразяват текущата реалност.
Пример 3 – Клауза HAVING
Можете да включите HAVING
клауза с вашия GROUP BY
клауза за филтриране на групите.
Пример:
SELECT
CountryCode,
District,
SUM(Population) AS Population
FROM City
WHERE CountryCode IN ('AGO', 'ARE', 'AUS')
GROUP BY CountryCode, District
HAVING SUM(Population) > 1000000
ORDER BY CountryCode;
Резултат:
+---------------+-----------------+--------------+ | CountryCode | District | Population | |---------------+-----------------+--------------| | AGO | Luanda | 2022000 | | AUS | New South Wales | 3993949 | | AUS | Queensland | 1805236 | | AUS | Victoria | 2990711 | | AUS | West Australia | 1096829 | +---------------+-----------------+--------------+
HAVING
Клаузата е подобна на WHERE
клауза, с изключение на WHERE
филтрира отделни редове, докато HAVING
филтри групи.
Също така, WHERE
клаузата филтрира данни преди той е групиран, докато HAVING
филтрира данни след то е групирано.
HAVING
клаузата приема същите оператори, които можете да използвате с WHERE
клауза (като =
, ) Operator for Beginners">>
, =) Operator for Beginners">>=
, IN
, LIKE
и др.).