Раздел GROUP BY при составлении запроса в SQL
Этот раздел предназначен для объединения результатов запроса в группы и расчета для каждой из них статистических значений. Иногда используют термин «сгруппированная таблица».
Синтаксическая форма
GROUP BY [{ROLLUP|CUBE|GROUPING SET}] (<список столбцов>) [HAVING <предикат>]
Примечания
При группировании следует учитывать следующие ограничения и особенности:
• Нельзя группировать строки по вычисляемым столбцам.
• Если в столбце, по которому производится группирование, существуют NULL-значения, то все они следуют в зависимости от СУБД в конце или в начале множества выходных строк.
• Возвращаемым столбцом может быть:
— Константа
— Функция агрегирования, возвращающая одно значения для всех строк группы
— Столбец (столбцы), по которому производится группирование
— Выражение, включающее перечисленные выше элементы
Примеры на группирование
SELECT SNum, MAX(Amt) FROM Orders GROUP BY SNum
SELECT SNum, Odate, MAX(Amt) AS MaxAmt FROM Orders GROUP BY SNum, Odate
SELECT SNum, Odate, MAX(Amt) FROM Orders WHERE Odate>10/03/1990 GROUP BY SNum, Odate
4) Варианты группирования
4.1) <список столбцов>
Например:
SELECT NYear, NQuarter, COUNT(*) AS Cnt FROM Orders GROUP BY NYear, NQuanter ORDER BY NYear, NQuarter
Результат группирования по списку столбцов:
NYear | NQuarter | Cnt | Пояснения |
2003 | 1 | 87 | Число заказов за I квартал |
2003 | 2 | 77 | Число заказов за II квартал |
2003 | 3 | 91 | Число заказов за III квартал |
2004 | 4 | 125 | Число заказов за IV квартал |
2004 | 1 | 139 | Число заказов за I квартал |
2004 | 2 | 119 | Число заказов за II квартал |
4.2) ROLLUP (<список столбцов>)
С ROLLUP обеспечивается вывод:
— Первоначально общих итогов
— Затем итогов по группам
— А после итогов каждой группы выводятся значения колонок, входящие в группу.
SELECT NYear, NQuarter, COUNT(*) AS Cnt FROM Orders GROUP BY ROLLUP(NYear, NQuarter) ORDER BY NYear, NQuarter
Результат группирования ROLLUP:
NYear | NQuarter | Cnt | Пояснения |
NULL | NULL | 648 | Общее число заказов |
2003 | NULL | 380 | Общее число заказов за 2003 |
2003 | 1 | 87 | Число заказов за I квартал |
2003 | 2 | 77 | Число заказов за II квартал |
2003 | 3 | 91 | Число заказов за III квартал |
2003 | 4 | 125 | Число заказов за IV квартал |
2004 | NULL | 268 | Общее число заказов за 2004 |
2004 | 1 | 139 | Число заказов за I квартал |
2004 | 2 | 119 | Число заказов за II квартал |
4.3) CUBE (<список столбцов>)
CUBE дополнительно к ROLLUP обеспечивает вывод после общих итогов еще и итогов одной колонки группирования по второй.
SELECT NYear, NQuarter, COUNT(*) AS Cnt FROM Orders GROUP BY CUBE(NYear, NQuarter) ORBER BY NYear, NQuarter
Результат группирования CUBE:
NYear | NQuarter | Cnt | Пояснения |
NULL | NULL | 648 | Общее число заказов |
NULL | 1 | 226 | Число заказов за I квартал за все годы |
NULL | 2 | 296 | Число заказов за II квартал за все годы |
NULL | 3 | 101 | Число заказов за III квартал за все годы |
NULL | 4 | 125 | Число заказов за IV квартал за все годы |
2003 | NULL | 380 | Общее число заказов за 2003 |
2003 | 1 | 87 | Число заказов за I квартал |
2003 | 2 | 77 | Число заказов за II квартал |
2003 | 3 | 91 | Число заказов за III картал |
2003 | 4 | 125 | Число заказов за IV картал |
2004 | NULL | 268 | Общее число заказов за 2004 |
2004 | 1 | 139 | Число заказов за I квартал |
2004 | 2 | 119 | Число заказов за II квартал |
4.4) GROUPING SET (<список столбцов>)
GROUPING SETS позволяет проводить агрегацию по нескольким группам в одном запросе. Для каждого набора групп запрос возвращает промежуточные итоги, где значение столбца группировки равно NULL. Фактически не выводит общих итогов по сравнению с ROLLUP.
SELECT NYear, NQuarter, COUNT(*) AS Cnt FROM Orders GROUP BY GROUNING SET((NYear, NQuarter),(NYear)) ORDER BY NYear, NQuarter
Результат группирования GROUPING SET:
NYear | NQuarter | Cnt | Пояснения |
2003 | NULL | 380 | Общее число заказов за 2003 |
2003 | 1 | 87 | Число заказов за I квартал |
2003 | 2 | 77 | Число заказов за II квартал |
2003 | 3 | 91 | Число заказов за III квартал |
2003 | 4 | 125 | Число заказов за IV квартал |
2004 | NULL | 268 | Общее число заказов за 2004 |
2004 | 1 | 139 | Число заказов за I квартал |
2004 | 2 | 119 | Число заказов за II квартал |
5) Подраздел HAVING
Этот подраздел предназначен для ограничения числа строк в сгруппированной таблице и является частью раздела GROUP BY. Предикат этого раздела строится по тем же семантическим правилам, что и в разделе WHERE, однако напрямую в предикате могут участвовать только те столбцы, которые указаны в раздел GROUP BY. Остальные можно использовать только внутри функций агрегирования.
Этот раздел ограничивает состав групп (подгрупп) строк, на которые разбивается результат запроса. В группы (подгруппы) включаются только те из множества возможных строк, для значений которых выполняются условия предиката раздела HAVING. Внутри раздела HAVING можно использовать вложенные запросы с функциями агрегирования, а также связанные подзапросы.
Примеры для подраздела HAVING:
SELECT SNum, Odate, MAX(Amt) FROM Orders GROUP BY SNum, Odate HAVING MAX(Amt)>3000
SELECT SNum, MAX(Amt) FROM Orders GROUP BY SNum HAVING SNum IN (1002, 1007)
SELECT Rating, COUNT (DISTINCT CNum) FROM Customer GROUP BY Rating HAVING Rating>(SELECT AVG(Rating) FROM Customer WHERE City=’San Jose’)
SELECT Odate, SUM(Amt) FROM Orders A GROUP BY Odate HAVING SUM(Amt)>(SELECT 2000+MIN(Amt) FROM Orders B WHERE A.Odate=B.Odate)