Sql group by rollup: MS SQL Server и T-SQL
Содержание
MS SQL Server и T-SQL
Расширения SQL Server для группировки
Последнее обновление: 19.07.2017
Дополнительно к стандартным операторам GROUP BY и HAVING SQL Server поддерживает еще четыре специальных расширения для группировки данных:
ROLLUP, CUBE, GROUPING SETS и OVER.
ROLLUP
Оператор ROLLUP добавляет суммирующую строку в результирующий набор:
SELECT Manufacturer, COUNT(*) AS Models, SUM(ProductCount) AS Units FROM Products GROUP BY Manufacturer WITH ROLLUP
Как видно из скриншота, в конце таблицы была добавлена дополнительная строка, которая суммирует значение столбцов.
Альтернативный синтаксис запроса, который можно использовать, начиная с версии MS SQL Server 2008:
SELECT Manufacturer, COUNT(*) AS Models, SUM(ProductCount) AS Units FROM Products GROUP BY ROLLUP(Manufacturer)
При группировке по нескольким критериям ROLLUP будет создавать суммирующую строку для каждой из подгрупп:
SELECT Manufacturer, COUNT(*) AS Models, SUM(ProductCount) AS Units FROM Products GROUP BY Manufacturer, ProductCount WITH ROLLUP
При сортировке с помощью ORDER BY следует учитывать, что она применяется уже после добавления суммирующей строки.
CUBE
CUBE похож на ROLLUP за тем исключением, что CUBE добавляет суммирующие строки для каждой комбинации групп.
SELECT Manufacturer, COUNT(*) AS Models, SUM(ProductCount) AS Units FROM Products GROUP BY Manufacturer, ProductCount WITH CUBE
GROUPING SETS
Оператор GROUPING SETS аналогично ROLLUP и CUBE добавляет суммирующую строку для групп. Но при этом он не включает сами группам:
SELECT Manufacturer, COUNT(*) AS Models, ProductCount FROM Products GROUP BY GROUPING SETS(Manufacturer, ProductCount)
При этом его можно комбинировать с ROLLUP или CUBE. Например, кроме суммирующих строк по каждой из групп добавим суммирующую строку для всех групп:
SELECT Manufacturer, COUNT(*) AS Models, ProductCount, SUM(ProductCount) AS Units FROM Products GROUP BY GROUPING SETS(ROLLUP(Manufacturer), ProductCount)
С помощью скобок можно определить более сложные сценарии группировки:
SELECT Manufacturer, COUNT(*) AS Models, ProductCount, SUM(ProductCount) AS Units FROM Products GROUP BY GROUPING SETS((Manufacturer, ProductCount), ProductCount)
OVER
Выражение OVER позволяет суммировать данные, при этому возвращая те строки, которые использовались для
получения суммированных данных. Например, найдем количество моделей и общее количество товаров этих моделей по производителю:
SELECT ProductName, Manufacturer, ProductCount, COUNT(*) OVER (PARTITION BY Manufacturer) AS Models, SUM(ProductCount) OVER (PARTITION BY Manufacturer) AS Units FROM Products
Выражение OVER ставится после агрегатной функции, затем в скобках идет выражение PARTITION BY и столбец,
по которому выполняется группировка.
То есть в данном случае мы выбираем название модели, производителя, количество единиц модели и добавляем к этому количество моделей для данного производителя и
общее количество единиц всех моделей производителя:
Понимание различий между CUBE и ROLLUP
Мое задание состояло в том, чтобы выяснить «how many invoices are written for each date?»
Я немного застрял и попросил моего профессора о помощи. Она отправила мне по электронной почте запрос, который отвечал бы на вопрос: «сколько печей каждого типа и версии было построено?
Для вызова, но без дополнительных очков, включите общее количество печей.»
Это был вопрос, который она мне послала:
SELECT STOVE.Type + STOVE.Version AS 'Type+Version'
, COUNT(*) AS 'The Count'
FROM STOVE
GROUP BY STOVE.Type + STOVE.Version WITH ROLLUP;
Поэтому я подправил этот запрос, пока он не удовлетворил мои потребности. Вот что я придумал:
SELECT InvoiceDt
, COUNT(InvoiceNbr) AS 'Number of Invoices'
FROM INVOICE
GROUP BY InvoiceDt WITH ROLLUP
ORDER BY InvoiceDt ASC;
И он вернул следующие результаты, которые я хотел.
Как бы то ни было, я решил почитать статью ROLLUP и начал со статьи из Microsoft . В нем говорилось, что предложение ROLLUP аналогично предложению CUBE, но отличается от предложения CUBE следующим образом:
- CUBE генерирует результирующий набор, который показывает агрегаты для всех комбинаций значений в выбранных столбцах.
- ROLLUP генерирует результирующий набор, который показывает агрегаты для иерархии значений в выбранных столбцах.
Поэтому я решил заменить ROLLUP в своем запросе на CUBE, чтобы посмотреть, что произойдет. Они дали те же результаты. Я предполагаю, что это где я путаюсь.
Похоже, что если вы используете тот тип запроса, который я здесь использую, то между этими двумя предложениями нет никакой практической разницы. Это правда? Или я чего-то не понимаю? Когда я закончил читать статью Microsoft, я подумал, что мои результаты должны были быть другими, используя предложение CUBE.
sql
sql-server
sql-server-2008
tsql
Поделиться
Источник
krebshack
13 августа 2011 в 21:41
4 ответа
- Как объединить CUBE и ROLLUP?
У меня есть запрос с важной агрегацией GROUP BY . Вот упрощенная схема ( SQL Fiddle ): CREATE TABLE [data] ( [year] [int] NOT NULL , [month] [int] NOT NULL , [country] [varchar] (32) NOT NULL , [state] [varchar] (32), [city] [varchar] (32) NOT NULL , [federation] [varchar] (32) NOT NULL , [id]…
- Когда использовать группирующие наборы, CUBE и ROLLUP
Недавно я узнал о группирующих наборах, CUBE и ROLLUP для определения нескольких группирующих наборов в sql server. Я спрашиваю, при каких обстоятельствах мы используем эти функции ? Каковы преимущества и преимущества их использования? SELECT shipperid, YEAR(shippeddate) AS shipyear, COUNT(*) AS…
158
Вы не увидите никакой разницы, так как вы сворачиваете только одну колонку. Рассмотрим пример, где мы это делаем
ROLLUP (YEAR, MONTH, DAY)
С ROLLUP
, он будет иметь следующие результаты:
YEAR, MONTH, DAY
YEAR, MONTH
YEAR
()
С CUBE
он будет иметь следующее:
YEAR, MONTH, DAY
YEAR, MONTH
YEAR, DAY
YEAR
MONTH, DAY
MONTH
DAY
()
CUBE
по существу содержит все возможные сценарии свертки для каждого узла, в то время как ROLLUP
будет поддерживать иерархию в такте (поэтому он не пропустит MONTH и не покажет YEAR/DAY,, в то время как CUBE
будет)
Вот почему вы не видели разницы, так как у вас была только одна колонка, которую вы сворачивали.
Надеюсь, это поможет.
Поделиться
Derek Kromm
13 августа 2011 в 23:25
77
Мы можем понять разницу между ROLLUP и CUBE на простом примере. Рассмотрим таблицу, которая содержит результаты ежеквартального тестирования студентов. В некоторых случаях мы должны видеть общую сумму, соответствующую четверти, а также студентам. Вот примерная таблица
SELECT * INTO #TEMP
FROM
(
SELECT 'Quarter 1' PERIOD,'Amar' NAME ,97 MARKS
UNION ALL
SELECT 'Quarter 1','Ram',88
UNION ALL
SELECT 'Quarter 1','Simi',76
UNION ALL
SELECT 'Quarter 2','Amar',94
UNION ALL
SELECT 'Quarter 2','Ram',82
UNION ALL
SELECT 'Quarter 2','Simi',71
UNION ALL
SELECT 'Quarter 3' ,'Amar',95
UNION ALL
SELECT 'Quarter 3','Ram',83
UNION ALL
SELECT 'Quarter 3','Simi',77
UNION ALL
SELECT 'Quarter 4' ,'Amar',91
UNION ALL
SELECT 'Quarter 4','Ram',84
UNION ALL
SELECT 'Quarter 4','Simi',79
)TAB
1. ROLLUP (можно найти итог для соответствующего одного столбца)
(а) получить общий балл каждого студента во всех четвертях.
SELECT * FROM #TEMP
UNION ALL
SELECT PERIOD,NAME,SUM(MARKS) TOTAL
FROM #TEMP
GROUP BY NAME,PERIOD
WITH ROLLUP
HAVING PERIOD IS NULL AND NAME IS NOT NULL
// Having is used inorder to emit a row that is the total of all totals of each student
Ниже приведен результат (а)
(Б) Если вам нужно получить общий балл за каждый квартал
SELECT * FROM #TEMP
UNION ALL
SELECT PERIOD,NAME,SUM(MARKS) TOTAL
FROM #TEMP
GROUP BY PERIOD,NAME
WITH ROLLUP
HAVING PERIOD IS NOT NULL AND NAME IS NULL
Ниже приведен результат (b)
2. CUBE (найти общее количество за квартал, а также студентов в одном кадре)
SELECT PERIOD,NAME,SUM(MARKS) TOTAL
FROM #TEMP
GROUP BY NAME,PERIOD
WITH CUBE
HAVING PERIOD IS NOT NULL OR NAME IS NOT NULL
Ниже приведен результат CUBE
Теперь вы можете задаться вопросом об использовании ROLLUP и CUBE в реальном времени. Иногда нам нужен отчет, в котором мы должны видеть итог каждой четверти и итог каждого студента в одном кадре. Вот пример
Я немного изменяю вышеприведенный запрос CUBE, так как нам нужен итог для обоих итогов.
SELECT CASE WHEN PERIOD IS NULL THEN 'TOTAL' ELSE PERIOD END PERIOD,
CASE WHEN NAME IS NULL THEN 'TOTAL' ELSE NAME END NAME,
SUM(MARKS) MARKS
INTO #TEMP2
FROM #TEMP
GROUP BY NAME,PERIOD
WITH CUBE
DECLARE @cols NVARCHAR (MAX)
SELECT @cols = COALESCE (@cols + ',[' + PERIOD + ']',
'[' + PERIOD + ']')
FROM (SELECT DISTINCT PERIOD FROM #TEMP2) PV
ORDER BY PERIOD
DECLARE @query NVARCHAR(MAX)
SET @query = 'SELECT * FROM
(
SELECT * FROM #TEMP2
) x
PIVOT
(
SUM(MARKS)
FOR [PERIOD] IN (' + @cols + ')
) p;'
EXEC SP_EXECUTESQL @query
Теперь вы получите следующий результат
Поделиться
Sarath Avanavu
01 декабря 2014 в 06:11
6
Это происходит потому, что у вас есть только один столбец, по которому вы группируетесь.
Добавьте Group by InvoiceDt, InvoiceCountry
(или любое другое поле, которое даст вам больше данных.
С помощью куба вы получите сумму для каждого InvoiceDt, и вы получите сумму для каждого InvoiceCountry.
Поделиться
JeffO
13 августа 2011 в 23:25
1
Вы можете найти более подробную информацию о группировке SET, CUBE, ROLL UP. TL;DR они просто расширяют группу на + UNION все в некотором роде, чтобы получить агрегацию 🙂
https://technet.microsoft.com/en-us/ library/bb510427(v=sql.105).aspx
Поделиться
o0omycomputero0o
04 января 2017 в 07:22
Похожие вопросы:
PostgreSQL:How для использования группирующих наборов, CUBE и ROLLUP для сводных итогов
У меня есть следующий фрагмент кода, который я написал в MySQL 5.6: INSERT INTO Totals SELECT Zone, State, COUNT(Sponsored), COUNT(Enrolled), COUNT(PickedUp) FROM MasterData GROUP BY Zone, StateName…
В чем разница между операторами cube, rollup и groupBy?
Вопрос в значительной степени заключен в названии. Я не могу найти никакой подробной документации относительно различий. Я действительно замечаю разницу, потому что при обмене вызовами функций cube…
Понимание ROLLUP в SQL
Я понял, что CUBE просто генерирует все перестановки, но у меня возникли проблемы с ROLLUP. Кажется, нет никаких хороших ресурсов в интернете или в книге, которую я читаю, для объяснения SQL для…
Как объединить CUBE и ROLLUP?
У меня есть запрос с важной агрегацией GROUP BY . Вот упрощенная схема ( SQL Fiddle ): CREATE TABLE [data] ( [year] [int] NOT NULL , [month] [int] NOT NULL , [country] [varchar] (32) NOT NULL ,…
Когда использовать группирующие наборы, CUBE и ROLLUP
Недавно я узнал о группирующих наборах, CUBE и ROLLUP для определения нескольких группирующих наборов в sql server. Я спрашиваю, при каких обстоятельствах мы используем эти функции ? Каковы…
Есть ли способ сделать ROLLUP или CUBE в R, как в sql?
Есть ли способ суммировать данные в R, используя такие функции, как ROLLUP и CUBE в sql? Если да, то может ли кто-нибудь указать мне направление примера?
Как Postgres реализует операторы CUBE -, ROLLUP-и группирующих множеств
Меня интересует, как Postgres реализует операторы CUBE -, ROLLUP-и группирующих множеств?
GROUP BY с несколькими наборами группировок, CUBE и ROLLUP предложениями
Сегодня я прочитал совет об использовании нескольких группирующих наборов, предложений CUBE и ROLLUP в предложении GROUP BY. Вы можете указать несколько наборов группировок, предложения CUBE и…
Нет ROLLUP и CUBE в PostgreSQL 9.4?
У меня есть несколько запросов, содержащих операторы rollup и cube. Когда я запускаю их на компьютере с PostgreSQL 9.4 и PgAdmin III, он говорит, что таких функций не существует. Те же самые запросы…
Разница между CUBE и с кубом
Я обнаружил, что в MSSQL существует и то, и другое SELECT <list of columns>, sum(measure) as measure FROM fact-table GROUP BY <list of columns> WITH CUBE и SELECT <list of…
MySQL 8.0: функция GROUPING — статьи sqlinfo.ru
Дата: 5.05.2017
Данная статья является переводом статьи Chaithra Gopalareddy.
Начиная с MySQL 8.0.1, сервер поддерживает SQL-функцию GROUPING. Эта функция используется для того, чтобы при использовании модификатора ROLLUP отличать NULL в строках с итоговыми/подытоговыми значениями от NULL в обычных строках.
Ведение
Сервер MySQL поддерживает модификатор ROLLUP при выполнении группирующих запросов. Ниже пример его использования:
mysql> create table t1 (a integer, b integer, c integer);
Query OK, 0 rows affected (0.05 sec)
mysql> insert into t1 values (111,11,11);
Query OK, 1 row affected (0.01 sec)
mysql> insert into t1 values (222,22,22);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1 values (111,12,12);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t1 values (222,23,23);
Query OK, 1 row affected (0.01 sec)
mysql> select * from t1;
+——+——+——+
| a | b | c |
+——+——+——+
| 111 | 11 | 11 |
| 222 | 22 | 22 |
| 111 | 12 | 12 |
| 222 | 23 | 23 |
+——+——+——+
4 rows in set (0.00 sec)
mysql> SELECT a, b, SUM(c) as SUM FROM t1 GROUP BY a,b WITH ROLLUP;
+——+——+——+
| a | b | SUM |
+——+——+——+
| 111 | 11 | 11 |
| 111 | 12 | 12 |
| 111 | NULL | 23 |
| 222 | 22 | 22 |
| 222 | 23 | 23 |
| 222 | NULL | 45 |
| NULL | NULL | 68 |
+——+——+——+
7 rows in set (0.00 sec)
Как видно из примера, использование модификатора ROLLUP добавляет строки, содержащие подытоги и заключительное итоговое значение, в которых у полей без агрегирующих функций стоит NULL.
Давайте добавим значения NULL в исходные данные таблицы:
mysql> INSERT INTO t1 values (1111,NULL,112);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO t1 values (NULL,112,NULL);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+——+——+——+
| a | b | c |
+——+——+——+
| 111 | 11 | 11 |
| 222 | 22 | 22 |
| 111 | 12 | 12 |
| 222 | 23 | 23 |
| 1111 | NULL | 112 |
| NULL | 112 | NULL |
+——+——+——+
6 rows in set (0.00 sec)
Теперь при использовании модификатора ROLLUP становится сложно понять — какие значения NULL относятся к обычным сгруппированным значениям, а какие указывают на подытоги и заключительное итоговое значение:
mysql> SELECT a, b, SUM(c) as SUM FROM t1 GROUP BY a,b WITH ROLLUP;
+——+——+——+
| a | b | SUM |
+——+——+——+
| NULL | 112 | NULL |
| NULL | NULL | NULL |
| 111 | 11 | 11 |
| 111 | 12 | 12 |
| 111 | NULL | 23 |
| 222 | 22 | 22 |
| 222 | 23 | 23 |
| 222 | NULL | 45 |
| 1111 | NULL | 112 |
| 1111 | NULL | 112 |
| NULL | NULL | 180 |
+——+——+——+
11 rows in set (0.01 sec)
Что нового в MySQL-8.0.1
В приведенном выше примере можно использовать функцию GROUPING, чтобы отличать NULL, добавляемые ROLLUP, от NULL, относящихся к сгруппированным значениям. Функция GROUPING, использующая в качестве аргумента имя поля, возвращает 1, если значение NULL в этом поле является результатом действия ROLLUP. В противном случае возвращается 0.
mysql> SELECT a, b, SUM(c) as SUM, GROUPING(a), GROUPING(b) FROM t1 GROUP BY a,b WITH ROLLUP;
+——+——+——+————-+————-+
| a | b | SUM | GROUPING(a) | GROUPING(b) |
+——+——+——+————-+————-+
| NULL | 112 | NULL | 0 | 0 |
| NULL | NULL | NULL | 0 | 1 |
| 111 | 11 | 11 | 0 | 0 |
| 111 | 12 | 12 | 0 | 0 |
| 111 | NULL | 23 | 0 | 1 |
| 222 | 22 | 22 | 0 | 0 |
| 222 | 23 | 23 | 0 | 0 |
| 222 | NULL | 45 | 0 | 1 |
| 1111 | NULL | 112 | 0 | 0 |
| 1111 | NULL | 112 | 0 | 1 |
| NULL | NULL | 180 | 1 | 1 |
+——+——+——+————-+————-+
11 rows in set (0.01 sec)
Как видно из примера, GROUPING(b) возвращает 1 только для тех строк, у которых в поле b стоит NULL, являющийся результатом действия ROLLUP (иными словами, для строк с подытогом).
Другой способ использования GROUPING — указать в качестве аргумента несколько столбцов. Тогда GROUPING вернет целое число, полученное из битовой маски, имеющей 1 у тех аргументов, для которых GROUPING(argument) равен 1. Например:
mysql> SELECT a, b, SUM(c) as SUM, GROUPING(a,b) FROM t1 GROUP BY a,b WITH ROLLUP;
+——+——+——+—————+
| a | b | SUM | GROUPING(a,b) |
+——+——+——+—————+
| NULL | 112 | NULL | 0 |
| NULL | NULL | NULL | 1 |
| 111 | 11 | 11 | 0 |
| 111 | 12 | 12 | 0 |
| 111 | NULL | 23 | 1 |
| 222 | 22 | 22 | 0 |
| 222 | 23 | 23 | 0 |
| 222 | NULL | 45 | 1 |
| 1111 | NULL | 112 | 0 |
| 1111 | NULL | 112 | 1 |
| NULL | NULL | 180 | 3 |
+——+——+——+—————+
11 rows in set (0.00 sec)
В данном примере GROUPING (a,b), возвращающая 3, означает, что значение NULL в столбце a и значение NULL в столбце b являются результатом действия ROLLUP. Для строк, у которых GROUPING(a,b) равно 1, значение NULL только в столбце b являются результатом действия ROLLUP.
Другие способы использования функции GROUPING
Функцию GROUPING можно использовать в части перечисления полей после ключевого слова SELECT или в части HAVING (условия отбора после группировки). Например, во втором случае можно получить отображение только тех строк, которые содержат итоговые/подытоговые значения, как показано в примере ниже:
mysql> SELECT a, b, SUM(c) as SUM FROM t1 GROUP BY a,b WITH ROLLUP HAVING GROUPING(a) = 1 or GROUPING(b) = 1;
+——+——+——+
| a | b | SUM |
+——+——+——+
| NULL | NULL | NULL |
| 111 | NULL | 23 |
| 222 | NULL | 45 |
| 1111 | NULL | 112 |
| NULL | NULL | 180 |
+——+——+——+
5 rows in set (0.00 sec)
Кроме того, с помощью функции GROUPING можно придать выборке удобный для восприятия вид:
mysql> SELECT IF(GROUPING(a)=1,’All Departments’, a) as Department, IF(GROUPING(b)=1, ‘All Employees’, b) as Employees, SUM(c) as SUM FROM t1 GROUP BY a,b WITH ROLLUP;
+——————+—————+——+
| Department | Employees | SUM |
+——————+—————+——+
| NULL | 112 | NULL |
| NULL | All Employees | NULL |
| 111 | 11 | 11 |
| 111 | 12 | 12 |
| 111 | All Employees | 23 |
| 222 | 22 | 22 |
| 222 | 23 | 23 |
| 222 | All Employees | 45 |
| 1111 | NULL | 112 |
| 1111 | All Employees | 112 |
| All Departments | All Employees | 180 |
+——————+—————+——+
11 rows in set (0.00 sec)
Это были некоторые из возможностей использования новой функции GROUPING.
Заключение
Мы хотели бы поблагодарить Zhe Dong за его вклад, который был использован в качестве основы при добавлении этой функциональности. Пожалуйста, протестируйте GROUPING и сообщите нам о своих пожеланиях.
Дата публикации: 5.05.2017
© Все права на данную статью принадлежат порталу SQLInfo.ru. Перепечатка в интернет-изданиях разрешается только с указанием автора и прямой ссылки на оригинальную статью. Перепечатка в бумажных изданиях допускается только с разрешения редакции.
Разница между сверткой и кубом — SQLServerCentral
Предложение GROUP BY используется для группировки результатов агрегатных функций в соответствии с указанным столбцом. Однако предложение GROUP BY не выполняет агрегированных операций на нескольких уровнях иерархии. Например, вы можете рассчитать общую заработную плату всех сотрудников для каждого отдела в компании (один уровень иерархии), но вы не можете рассчитать общую заработную плату всех сотрудников, независимо от того, в каком отделе они работают (два уровня иерархии).
Операторы
ROLLUP позволяют расширить функциональные возможности предложений GROUP BY, вычисляя промежуточные и общие итоги для набора столбцов. Оператор CUBE аналогичен по функциональности оператору ROLLUP; однако оператор CUBE может вычислять промежуточные и общие итоги для всех перестановок столбцов, указанных в нем.
В этой статье мы рассмотрим операторы ROLLUP и CUBE на простом примере. Это позволит нам увидеть практические различия между ними и понять, когда следует использовать каждый из них.
Создание фиктивных данных
Давайте создадим фиктивные данные, по которым мы сможем выполнять наши примеры запросов. Создайте новую базу данных под названием «компания», а затем запустите приведенный ниже код, чтобы создать таблицу «сотрудников».
ЕГЭ компании; СОЗДАТЬ ТАБЛИЦУ сотрудника ( id INT ПЕРВИЧНЫЙ КЛЮЧ, name VARCHAR (50) NOT NULL, пол VARCHAR (50) NOT NULL, зарплата INT NOT NULL, отдел VARCHAR (50) NOT NULL )
Теперь, когда у нас настроены наша база данных и таблица, нам нужно заполнить ее фиктивными данными для работы.
INSERT INTO сотрудник ЗНАЧЕНИЯ (1, Дэвид, Мужчина, 5000, Продажи), (2, «Джим», «Женский», 6000, «HR»), (3, «Катя», «Женщина», 7500, «ИТ»), (4, «Воля», «Мужской», 6500, «Маркетинг»), (5, «Шейн», «Женский», 5500, «Финансы»), (6, Сарай, Мужской, 8000, Продажи), (7, Вик, Мужской, 7200, HR), (8, «Винс», «Женщина», 6600, «ИТ»), (9, «Джейн», «Женщина», 5400, «Маркетинг»), (10, «Лаура», «Женский», 6300, «Финансы»), (11, Mac, Мужской, 5700, Продажи), (12, «Пат», «Мужской», 7000, «HR»), (13, «Джули», «Женщина», 7100, «ИТ»), (14, «Элис», «Женщина», 6800, «Маркетинг»), (15, Уэйн, Мужчина, 5000, Финансы)
Simple GROUP BY Пункт
Давайте начнем с простого предложения GROUP BY, чтобы вычислить сумму зарплат всех сотрудников, сгруппированных по их отделам.
ВЫБЕРИТЕ отдел, сумма (зарплата) как Salary_Sum ОТ сотрудника ГРУППА ПО отделам
Это вернет следующее:
Отдел | Заработная плата_Сумма |
Финансы | 16800 |
HR | 20200 |
IT | 21200 |
Маркетинг | 18700 |
Продажи | 18700 |
Здесь вы можете увидеть сумму зарплат всех сотрудников, сгруппированных по их отделам.Однако мы не можем увидеть общую сумму, которая представляет собой сумму зарплат всех сотрудников, принадлежащих ко всем отделам компании.
Другой способ взглянуть на это — сказать, что предложение GROUP BY не извлекает общую сумму зарплат всех сотрудников компании. Здесь пригодится оператор ROLLUP.
Оператор ROLLUP
Как упоминалось ранее, оператор ROLLUP используется для вычисления промежуточных и общих итогов для набора столбцов, переданных в предложение «GROUP BY ROLLUP».
Давайте посмотрим, как предложение ROLLUP помогает нам рассчитать общую зарплату сотрудников, сгруппированных по их отделам, и общую сумму зарплат всех сотрудников в компании. Для этого мы рассмотрим простой пример запроса.
SELECT coalesce (отдел, "Все отделы") AS Отдел, сумма (зарплата) как Salary_Sum ОТ сотрудника ГРУППА ПО РОЛИКЕ (отдел)
В этом коде мы использовали оператор ROLLUP для вычисления итоговой суммы зарплат сотрудников всех отделов.Однако для общего итога ROLLUP вернет NULL для отдела. Чтобы избежать этого, мы использовали предложение «Coalesce». Это заменит NULL текстом «Все отделы» и отобразит название каждого отдела в столбце «Отдел». Подробнее об использовании «Coalesce» см. В этой статье.
Отдел | Заработная плата_Сумма |
Финансы | 16800 |
HR | 20200 |
IT | 21200 |
Маркетинг | 18700 |
Продажи | 18700 |
Все отделы | 95600 |
Поиск промежуточных итогов с помощью оператора ROLLUP
Оператор ROLLUP также может использоваться для вычисления промежуточных итогов для каждого столбца на основе группировок в этом столбце.
Давайте рассмотрим пример, в котором нам нужна сумма окладов сотрудников на уровне отдела и пола, а также промежуточная сумма вместе с общей суммой для всех зарплат всех сотрудников мужского и женского пола, принадлежащих ко всем отделам.
ВЫБРАТЬ coalesce (отдел, "Все отделы") Отдел AS, coalesce (пол, "Все полы") КАК Пол, сумма (зарплата) как Salary_Sum ОТ сотрудника ГРУППА ПО РОЛИКЕ (отдел, пол)
Этот запрос возвращает приведенную ниже таблицу.Как видите, он возвращает сумму зарплат сотрудников каждого отдела, разделенную на три категории: мужские, женские и все пола. Промежуточные итоги — это строки со словом «Все» в них. Последняя строка — это общая сумма, поэтому в обоих столбцах есть «Все».
NB: Для целей этой статьи я выделил полужирным шрифтом «Все» в таблице ниже, чтобы выделить их, это не то, как они выглядят на самом деле.
Отдел | Пол | Заработная плата_Сумма |
Финансы | Женский | 11800 |
Финансы | Мужской | 5000 |
Финансы | Для всех полов | 16800 |
HR | Женский | 6000 |
HR | Мужской | 14200 |
HR | Для всех полов | 20200 |
IT | Женский | 21200 |
IT | Для всех полов | 21200 |
Маркетинг | Женский | 12200 |
Маркетинг | Мужской | 6500 |
Маркетинг | Для всех полов | 18700 |
Продажи | Мужской | 18700 |
Продажи | Для всех полов | 18700 |
Все отделы | Для всех полов | 95600 |
Не беспокойтесь, что вы не видите общую зарплату сотрудников-мужчин в ИТ-отделе.Это потому, что их нет, как в случае с женщинами-сотрудниками в отделе продаж.
Оператор КУБА
Оператор CUBE также используется в сочетании с предложением GROUP BY, однако оператор CUBE дает результаты, генерируя все комбинации столбцов, указанные в предложении GROUP BY CUBE.
Давайте воспользуемся им, чтобы найти зарплаты, сгруппированные по отделам и полу. Если мы внимательно посмотрим на эти две колонки, то увидим четыре возможных комбинации, с помощью которых мы можем сгруппировать заработную плату по отделам и полу.Это следующие:
- Заработная плата с разбивкой по отделам и полу
- Заработная плата только по полу
- Заработная плата, сгруппированная только по отделам
- Итого по всем зарплатам
Выполните следующий сценарий, чтобы увидеть эти четыре комбинации в наборе результатов.
ВЫБРАТЬ coalesce (отдел, "Все отделы") Отдел AS, coalesce (пол, "Все полы") КАК Пол, сумма (зарплата) как Salary_Sum ОТ сотрудника ГРУППА ПО КУБУ (отдел, пол)
Результат вышеупомянутого скрипта выглядит следующим образом:
№ ряда | Отдел | Пол | Заработная плата_Сумма |
1 | Финансы | Женский | 11800 |
2 | HR | Женский | 6000 |
3 | IT | Женский | 21200 |
4 | Маркетинг | Женский | 12200 |
5 | Все отделы | Женский | 51200 |
6 | Финансы | Мужской | 5000 |
7 | HR | Мужской | 14200 |
8 | Маркетинг | Мужской | 6500 |
9 | Продажа | Мужской | 18700 |
10 | Все отделы | Мужской | 44400 |
11 | Все отделы | Все гендеры | 95600 |
12 | Финансы | Все гендеры | 16800 |
13 | HR | Все гендеры | 20200 |
14 | IT | Все гендеры | 21200 |
15 | Маркетинг | Все гендеры | 18700 |
16 | Продажа | Все гендеры | 18700 |
Давайте найдем четыре комбинации, по которым сгруппирована заработная плата в приведенном выше выходе.
NB: Я добавил номера строк, чтобы очистить ссылки на записи в наборе результатов. Их фактически нет в наборе результатов.
- В первых четырех строках и в строках с 6 по 9 зарплаты сгруппированы по отделам и полу.
- В строке 5 -й и 10 -й заработная плата сгруппирована только по полу, т.е. женщины и мужчины, работающие во всех отделах.
- В строке 11 -й мы можем увидеть общую сумму заработных плат сотрудников всех полов и всех отделов.
- В последних пяти строках, то есть строках с 12 по 16, зарплаты сгруппированы только по отделам.
Итак, мы можем видеть все четыре комбинации, которые мы обсуждали ранее в выходных данных выше.
Разница между ROLLUP и CUBE
Есть только одно существенное различие между функциями оператора ROLLUP и оператора CUBE. Оператор ROLLUP генерирует агрегированные результаты для выбранных столбцов в иерархическом порядке. С другой стороны, CUBE генерирует агрегированный результат, содержащий все возможные комбинации для выбранных столбцов.
Чтобы понять это, посмотрите на набор результатов для оператора ROLLUP, где сумма зарплат сотрудников сгруппирована по отделам и полу:
Номер строки | Отдел | Пол | Заработная плата_Сумма |
1 | Финансы | Женский | 11800 |
2 | Финансы | Мужской | 5000 |
3 | Финансы | Все гендеры | 16800 |
4 | HR | Женский | 6000 |
5 | HR | Мужской | 14200 |
6 | HR | Все гендеры | 20200 |
7 | IT | Женский | 21200 |
8 | IT | Все гендеры | 21200 |
9 | Маркетинг | Женский | 12200 |
10 | Маркетинг | Мужской | 6500 |
11 | Маркетинг | Все гендеры | 18700 |
12 | Продажа | Мужской | 18700 |
13 | Продажа | Все гендеры | 18700 |
14 | Все отделы | Все гендеры | 95600 |
Здесь данные агрегированы иерархически.В строках 1, 2, 4, 5, 7, 9, 10 и 12 зарплаты сгруппированы по отделам и полу. В строках 3, 6, 8, 11 и 13 зарплаты сгруппированы только по департаментам.
Наконец, в строке 14 у нас есть общая сумма зарплат всех сотрудников всех полов из всех отделов. Здесь мы имеем три комбинации, которые имеют иерархический характер. Это следующие:
- Отдел и пол
- Отдел
- Всего
У нас нет заработной платы только по полу.Это потому, что пол находится на самом низком уровне иерархии.
С другой стороны, если вы посмотрите на агрегированный результат оператора CUBE, где сумма зарплат сотрудников была сгруппирована по отделам и полу, у нас были все четыре возможных комбинации:
- 1- Отдел и пол
- 2- Только отдел
- 3- только пол
- 4- Всего.
или
Примечание: Здесь важно отметить, что результаты операторов ROLLUP и CUBE будут одинаковыми, если ваши данные сгруппированы только по одному столбцу.
Какой мне использовать?
ROLLUP и CUBE — это инструменты для повышения производительности. Вам следует использовать ROLLUP, если вы хотите, чтобы ваши данные были иерархическими, и CUBE, если вам нужны все возможные комбинации.
Например, если вы хотите получить общую численность населения страны, штата и города. ROLLUP суммирует население на трех уровнях. Сначала он вернет сумму населения на уровне страны-государства-города. Затем он суммирует население на уровне страны-государства и, наконец, суммирует население на уровне страны.Это также обеспечило бы общий общий уровень.
CUBE группирует данные во всех возможных комбинациях столбцов, чтобы совокупность суммировалась по следующим уровням:
- Страна-государство-город
- Стейт-Сити
- Город
- Страна-штат
- Государство
- Загородный город
- Страна
- Все
Все зависит от того, что вам нужно, что бы вы выбрали. Простое практическое правило: если у вас есть иерархические данные (например, страна-> штат-> город или отдел-> менеджер-продавец и т. Д.), вам обычно нужны иерархические результаты, и вы используете ROLLUP для группировки данных.
Если у вас есть неиерархические данные (например, город-пол-национальность), вам не нужны иерархические результаты, поэтому вы используете CUBE, поскольку он предоставит все возможные комбинации.
вопросов о наборах CUBE, ROLLUP и GROUPING, которые вы стеснялись задать
- А? Что такое GROUPING SET, CUBE и ROLLUP в SQL?
- Почему мне могут быть полезны ROLLUP или CUBE?
- Это стандартный SQL или только Microsoft?
- Могу ли я исключить один или несколько столбцов из ROLLUP?
- Что же тогда такое НАБОРЫ ГРУППИРОВКИ? Я должен знать о них?
- Зачем нам нужно объединять столбцы в агрегации?
- Есть ли в ГРУППИРОВАНИИ НАБОРЫ нечто большее, чем способ создания КУБОВ ‘à la carte’?
- Почему предусмотрены функции Grouping () и Grouping_ID ()?
1.А? Что такое GROUPING SET, CUBE и ROLLUP в SQL?
CUBE, ROLLUP и GROUPING SET — необязательные операторы предложения GROUP BY оператора SELECT для создания отчетов с большим объемом информации. Они позволяют выполнять несколько операций GROUP BY в одном операторе, потенциально экономя много времени и вычислительных ресурсов. Они могут предоставить всю информацию, необходимую для составления отчетов, включая итоги, обеспечивая при этом хорошую производительность для больших таблиц и помогая оптимизатору запросов разработать хороший план выполнения.
Дополнительные строки «суперагрегат» предоставляют сводные значения, что позволяет использовать несколько «агрегатов», таких как SUM () или MAX (), в одном результате. NULL в этих строках в результате предназначены для обозначения «все», а не «неизвестно». Это позволяет получить все необходимые агрегаты за один проход по таблице. Из-за наличия дополнительных строк в результатах предусмотрены дополнительные функции GROUPING (),
и GROUPING_ID ()
, чтобы указать эти дополнительные «супергагрегированные» строки и то, какие столбцы агрегируются.
Это имеет большой смысл, если у вас есть приложение, которое должно запускать несколько отчетов без дополнительных вычислений или без возврата к базе данных: у вас есть все, что вам нужно, в одном результате.
Возьмите этот стандартный пример ROLLUP (здесь я использую AdventureWorks 2012).
SELECT t. [Группа] AS регион, t.name AS территория, сумма (TotalDue) AS выручка, datepart (yyyy, OrderDate) AS [год], datepart (mm, OrderDate) AS [месяц] FROM Продажи.SalesOrderHeader s INNER JOIN Sales.SalesTerritory T ON s.TerritoryID = T.TerritoryID GROUP BY t. [Group], t.name, datepart (yyyy, OrderDate), datepart (mm, OrderDate) WITH ROLLUP |
Помимо простых агрегатных строк GROUP BY с итоговой суммой за каждый месяц, которые вы получите при простой группировке, вы также получите промежуточные или супергрегатные строки, а также строку общего итога. (вот начало результата)
Тот NULL, который я выделил, означает, что строка представляет собой агрегат за «все» месяцы 2005 года во Франции (часть региона Европы)
Помимо всего этого, вы получаете общую сумму к оплате за каждый год, для каждой территории и территориальной группы, а также полную сумму к оплате.(с конца)
Эти NULL означают «Все», помните. Последняя строка — это общая сумма, а над ней — сумма для Тихоокеанского региона. Выше этого — вклад Австралии в Тихоокеанский регион. Четвертая строка снизу — это вклад Австралии за 2008 год. Количество возвращаемых группировок на единицу больше, чем количество выражений в списке составных элементов, предоставленных оператору GROUP BY.
Чтобы получить тот же эффект без использования свертки, вам нужно сделать что-то вроде этого (AdventureWorks2012)
1 2 3 4 5 6 7 8 9 10 11 12 13 140002 14 18 19 20 21 | ; С myGrouping (регион, территория, totalDue, [год], [месяц]) AS (ВЫБЕРИТЕ t.[Group], t.name, sum (TotalDue) AS выручка, datepart (yyyy, OrderDate) AS [год], datepart (mm, OrderDate) AS [месяц] FROM Sales.SalesOrderHeader s INNER JOIN Sales .SalesTerritory T ON s.TerritoryID = T.TerritoryID GROUP BY t.name, t. [Group], datepart (yyyy, OrderDate), datepart (mm, OrderDate)) SELECT Region, region, totalDue, [год ], [месяц] FROM myGrouping UNION ALL SELECT Регион, территория, сумма (totalDue), [год], NULL FROM myGrouping ГРУППА ПО Региону, территории, [год] UNION ALL SELECT Регион, территория, сумма (totalDue), NULL, NULL FROM myGrouping GROUP BY Region, территория UNION ALL SELECT Region, NULL, sum (totalDue), NULL, NULL FROM myGrouping GROUP BY Region UNION ВСЕ ВЫБРАТЬ NULL, NULL, sum (totalD ue), NULL, NULL ОТ myGrouping |
Которая намного дороже процессора и ввода-вывода.Обратите внимание, что стандартный синтаксис предложения GROUP BY в последних версиях —
.
… ‘GROUPBY ROLLUP (t. [Группа], t.name, datepart (yyyy, OrderDate), datepart (mm, OrderDate))’ |
Этот новый синтаксис дает вам некоторые дополнительные функции. Помните также, что порядок столбцов влияет на группировку вывода ROLLUP и может влиять на количество строк в наборе результатов.
CUBE делает то же самое, но вместо предоставления иерархии итогов в упорядоченных строках суперагрегатов, он предоставляет все перестановки «суперагрегатов» (строки «симметричных суперагрегатов»), так называемые перекрестные табличные строки. Если вы хотите знать, какая территория отдала больше всего приказов в марте или какая территория была наименее успешной в 2006 году, вам понадобится CUBE. Вы подводите к результату все возможные суммы.
GROUPING SET позволяет точно настроить результат для предоставления более специализированной информации помимо CUBE.Он может предоставить сводную информацию о комбинациях измерений. Вы можете получить точно такой же результат, что и в нашем примере ROLLUP, используя GROUPING SETS, но с гораздо большим набором текста.
SELECT t. [Группа] AS регион, t.name AS территория, сумма (TotalDue) AS выручка, datepart (yyyy, OrderDate) AS [год], datepart (mm, OrderDate) AS [месяц] FROM Sales.SalesOrderHeader s ВНУТРЕННЕЕ СОЕДИНЕНИЕ Продажи.SalesTerritory T ON s.TerritoryID = T.TerritoryID GROUP BY GROUPING SETS ( (T. [Group], T.name, datepart (yyyy, OrderDate), datepart (mm, OrderDate)), (T. [Группа], T.name, datepart (yyyy, OrderDate)), (T. [Group], T.name), (T. [Group]), ()) |
Это просто для того, чтобы показать, как они связаны. На самом деле вы прибегли бы к GROUPING SETS, чтобы получить результаты, которые невозможны с ROLLUP или CUBE.
Почти все эти сводные данные можно получить, используя только GROUP BY, но только путем многократного группирования результата GROUP BY или выполнения более одного прохода через данные.
Когда вы используете CUBE, ROLLUP или GROUPING SETS, вы не можете использовать ключевое слово DISTINCT в агрегатных выражениях, таких как AVG (DISTINCT имя_столбца), COUNT (DISTINCT имя_столбца) и SUM (DISTINCT имя_столбца)
2. Почему мне могут быть полезны ROLLUP или CUBE?
Расцвет
ROLLUP и CUBE был еще до SSAS.Они были полезны для предоставления тех же возможностей, что и куб в OLAP. Тем не менее, он все еще имеет свое применение. В AdventureWorks это излишне, но если вы обрабатываете большие объемы данных, вам нужно передать свои данные только один раз и сделать как можно больше с данными, которые были агрегированы. События, которые произошли в прошлом, изменить нельзя, поэтому редко требуется сохранять исторические данные в активной OLTP-системе. Вместо этого вам нужно только сохранить агрегированные данные на уровне детализации («детализации»), необходимом для всех прогнозируемых отчетов.
Представьте, что вы отвечаете за сообщение о телефонном коммутаторе, который принимает около двух миллионов звонков в день. Если вы сохраните все эти вызовы на своем OLTP-сервере, вы скоро обнаружите, что SQL Server трудится над отчетами об использовании. Вы должны сохранять исходную информацию о звонках в течение установленного законом периода времени, но вы определяете из бизнеса, что их, самое большее, интересует только количество звонков в минуту. Затем вы снизили требования к хранилищу на сервере OLTP до 1.4% от того, что было, а записи звонков могут быть заархивированы на другой SQL Server для специальных запросов и заявлений клиентов. Скорее всего, стоит сэкономить. Предложения CUBE и ROLLUP позволяют даже сохранять итоги по строкам, итоги по столбцам и общие итоги без необходимости выполнять сканирование сводной таблицы таблицей или кластеризованным индексом.
Пока в эти данные не вносятся ретроспективные изменения и все периоды времени завершены, вам никогда не придется повторять или изменять агрегаты, основанные на прошлых периодах времени, хотя общие итоги придется переписать !.
Давайте притворимся, но используем AdventureWorks2012, чтобы вы могли подыгрывать.
Сначала создадим временную сводную таблицу.
1 2 3 4 5 6 7 8 9 10 11 12 13 140002 18 19 | ЕСЛИ СУЩЕСТВУЕТ (ВЫБРАТЬ * ИЗ tempdb.sys.tables ГДЕ имя LIKE ‘# AggregationTable%’) DROP TABLE #aggregationTable — удалить временную таблицу, если она существует GO SELECT identity (INT, 1,1) AS [суррогат], — поэтому у нас может быть уникальный столбец т. [Группа] Регион AS, t.name территория AS, сумма (TotalDue) AS выручка, datepart (yyyy, OrderDate) AS [год], datepart (mm, OrderDate) AS [месяц], группировка (t.name) AS isNameGroup, — Относится ли это ко ВСЕМ территориям группировка (t.[Group]) AS isGroupGroup, — Относится ли это ко ВСЕМ континентам группировка (datepart (yyyy, OrderDate)) AS isYearGroup, — Относится ли это ко ВСЕМ годам группировка (datepart (mm, OrderDate)) AS isMonthGroup , — относится ли это ко ВСЕМ месяцам Grouping_ID (t.name, t. [Group], datepart (yyyy, OrderDate), datepart (mm, OrderDate)) AS isGroupingRow — это дополнительный не -строка данных, содержащая агрегированные данные INTO #AggregationTable FROM Sales.SalesOrderHeader s INNER JOIN Sales.SalesTerritory T ON s.TerritoryID = T.TerritoryID GROUP BY t.name, t. [Group], datepart (yyyy, OrderDate), datepart (mm, OrderDate) WITH ROLLUP |
Обратите внимание, что мы добавляем дополнительные «битовые» столбцы, которые сообщают нам, какие строки содержат строки сводки. Если вы по ошибке добавите их в какие-либо дополнительные агрегаты, вы получите серьезно завышенные результаты. Очевидно, что вы не можете использовать Grouping (),
или Grouping_ID для сохраненного результата, поэтому вам следует предоставить что-то взамен.
Теперь мы можем очень быстро создать сводную таблицу
1 2 3 4 5 6 7 8 9 10 11 12 13 140002 18 19 | — теперь мы можем создать простую сводную таблицу с итоговой строкой и — столбцом SELECT Territory, sum (CASE [год] WHEN 2005 THEN выручка ELSE 0 END) AS [2005], sum (СЛУЧАЙ [год] КОГДА 2006 ТОГДА выручка ИНАЧЕ 0 КОНЕЦ) КАК [2006], сум (ПРИМЕР [год] КОГДА 2007 ТОГДА выручка ИНАЧЕ 0 КОНЕЦ) КАК [2007], сум (ВАРИАНТ [год] КОГДА 2008 ТОГДА выручка ELSE 0 END) AS [2008], сумма (выручка) AS [общая территория] FROM #AggregationTable WHERE isGroupingrow = 0 GROUP BY территория UNION ALL SELECT ‘Total’, sum ( ВАРИАНТ [год] КОГДА 2005 ТОГДА выручка ИНАЧЕ 0 КОНЕЦ) КАК [2005], сум (ВАРИАНТ [год] КОГДА 2006 ТОГДА доход ИНАЧЕ 0 КОНЕЦ) КАК [2006], сум (ВАРИАНТ [год] КОГДА 2007 ТОГДА доход ИНАЧЕ 0 КОНЕЦ) КАК [2007], сум (ВАРИАНТ [год] КОГДА 2008 ТОГДА выручка ИНАЧЕ 0 КОНЕЦ) КАК [2008], сумма (доход) AS [общая территория] ИЗ #AggregationTable ГДЕ isYearGroup = 0 И isMonthGroup = 1 |
Итак, менеджеры быстро улыбаются, увидев это, но затем они ярко говорят: «Я уверен, что я также попросил разбивку по территории в месяц.
Вы делаете это с коротким смешком.
1 2 3 4 5 6 7 8 9 10 11 12 13 140002 14 18 19 20 21 22 23 24 25 26 27 28 29 31 | ВЫБРАТЬ дата (МЕСЯЦ, добавление даты (МЕСЯЦ, [МЕСЯЦ], ’01 дек 2000′)) КАК [месяц], Сумма (СЛУЧАЙ, территория КОГДА «Австралия» ТО доход ELSE 0 КОНЕЦ) КАК [Австралия], сум (КЕЙС-территория, КОГДА «Канада», ТО доход ЕЩЕ 0 КОНЕЦ) КАК [Канада], сум (ПРИМЕР территория, КОГДА «Центральная», ТО доход ИНАЧЕ 0 КОНЕЦ) КАК [Центральная], сум (ПРИМЕРНАЯ территория КОГДА » Франция ‘ТОГДА доход ELSE 0 КОНЕЦ) КАК [Франция], сум (ПРИМЕР территория, КОГДА «Германия» ТОГДА доход ИНАЧЕ 0 КОНЕЦ) КАК [Германия], сум (ПРИМЕР территория КОГДА «Северо-восток» ТО доход еще 0 КОНЕЦ) AS [Северо-восток], сум (CASE территория, КОГДА «Северо-запад» THEN выручка ELSE 0 КОНЕЦ) AS [Northwest], сум (CASE территория WHEN ‘Southeast’ THEN выручка ELSE 0 END) AS [Southeast], sum (Территория СЛУЧАЯ, КОГДА «Юго-запад», ТО доход ELSE 0 КОНЕЦ) КАК [Юго-запад], сум (СЛУЧАЙ территория W HEN ‘United Kingdom’ THEN выручка ELSE 0 END) AS [United Kingdom], сумма (выручка) AS [Всего за месяц] ИЗ #AggregationTable ГДЕ isGroupingrow = 0 GROUP BY month UNION ALL ВЫБЕРИТЕ ‘Итого’, сум (ПРИМЕР территория, КОГДА «Австралия» ТОГО доход ИНАЧЕ 0 КОНЕЦ) КАК [Австралия], сум (ПРИМЕР территория КОГДА «Канада» ТОГДА доход ИНАЧЕ 0 КОНЕЦ) КАК [Канада], сум (ПРИМЕР территория, КОГДА «Центральный», ТОГДА доход ELSE 0 КОНЕЦ) КАК [Центральный], сум (ПРИМЕР территория, КОГДА «Франция» ТОГДА доход ИНАЧЕ 0 КОНЕЦ) КАК [Франция], сум (ПРИМЕР территория КОГДА ‘Германия ‘THEN выручка ELSE 0 END) AS [Германия], сум (CASE территория, КОГДА «Северо-восток» THEN выручка ELSE 0 END) AS [Северо-восток], sum (CASE территория, WHEN’ Northwest ‘THEN выручка ELSE 0 END) AS [Северо-запад], сум (ДЕЛО территория КОГДА ‘Южный ast ‘ТОГДА доход ELSE 0 КОНЕЦ) КАК [Юго-восток], сум (ПРИМЕР территория, КОГДА «Юго-запад» ТОГДА доход ELSE 0 КОНЕЦ) КАК [Юго-запад], сум (ПРИМЕР территория КОГДА «Соединенное Королевство» THEN выручка ELSE 0 КОНЕЦ ) AS [Соединенное Королевство], сумма (доход) AS [Всего за месяц] ИЗ #AggregationTable WHERE isGroupingrow = 0 |
Но если вы использовали CUBE вместо Rollup, последняя строка «total» уже была бы вычислена.В реальном примере на создание отчета потребуется время. Вы можете создать КУБ в десяти измерениях; хотя они имеют тенденцию увеличивать агрегирование, они не слишком дороги.
3. Это стандартный SQL или только Microsoft?
Теперь это стандартный ANSI SQL с 1999 года, хотя WITH CUBE и WITH ROLLUP были впервые представлены Microsoft. Это включение несколько удивительно, поскольку они вводят второе значение, «все», для значения NULL помимо «неизвестно». Когда Microsoft впервые представила CUBE и ROLLUP, синтаксис немного отличался, но обе формы разрешены в SQL Server.В одном операторе SELECT можно использовать только один стиль синтаксиса, и вы должны использовать синтаксис, совместимый с ISO, для всей новой работы.
4. Могу ли я исключить один или несколько столбцов из ROLLUP?
Если хотите! Представьте, что мне не нужен суперсводный итог по всем регионам ( т. [Группа])
SELECT t. [Группа] AS регион, t.name AS территория, сумма (TotalDue) AS выручка, datepart (yyyy, OrderDate) AS [год], datepart (mm, OrderDate) AS [месяц] FROM Продажи.SalesOrderHeader s INNER JOIN Sales.SalesTerritory T ON s.TerritoryID = T.TerritoryID GROUP BY t. [Группа], ROLLUP (t.name, datepart (yyyy, OrderDate), datepart (mm, OrderDate)) |
Здесь мы используем синтаксис, совместимый с ANSI SQL 2006. То же самое можно сделать и с кубом. Я никогда не находил для этого практического применения, но вы могли встретить это
5. Что же тогда такое НАБОРЫ ГРУППИРОВКИ? Я должен знать о них?
GROUPING SET означает, что вы просите SQL сгруппировать результат несколько раз.Вы можете использовать синтаксис GROUPING SETS, чтобы точно указать, какие агрегаты вычислять. Вот пример.
SELECT t. [Группа] AS регион, t.name AS территория, сумма (TotalDue) AS выручка, datepart (yyyy, OrderDate) AS [год], datepart (mm, OrderDate) AS [месяц] FROM Sales.SalesOrderHeader s INNER JOIN Sales.SalesTerritory T ON s.TerritoryID = T.TerritoryID GROUP BY t. [ГРУППА], НАБОРЫ ГРУППИРОВКИ (ROLLUP (t.name), ROLLUP (datepart (yyyy, OrderDate), datepart (mm, OrderDate))) |
Здесь вы запрашиваете разбивку по группам территорий для каждого месяца каждого года с итогами за месяц и год, за которыми следует итоговая сумма по названию территории, но без итоговой суммы. В отличие от ROLLUP, вы получаете тот же результат независимо от порядка столбцов в каждом НАБОРЕ ГРУППИРОВКИ и порядка НАБОРОВ ГРУППИРОВКИ.
Наборы
GROUPING SET могут дать вам именно то, что дают вам CUBE и ROLLUP, и многое другое. Как вы можете видеть в последнем примере, вы можете использовать стандартные «table d’hôte» CUBE и ROLLUP, смешанные с прямо выраженными «à la carte» GROUPING SET.
6. Зачем нам нужно объединять столбцы в агрегации?
Если в некоторых отчетах необходимо объединить два столбца, полезно объявить агрегирование, которое объединяет два столбца. В первом примере мы объединяем год и месяц для сведения, в результате чего итоги ограничиваются только каждой территорией,
.
— получить итоги только для каждой территории — нет итогов для каждого региона или года ВЫБРАТЬ t.[Группа] Регион AS, t.name Территория AS, сумма (TotalDue) AS выручка, datepart (yyyy, OrderDate) AS [год], datepart (mm, OrderDate) AS [месяц] FROM Sales.SalesOrderHeader s INNER JOIN Sales.SalesTerritory T ON s.TerritoryID = T.TerritoryID GROUP BY t. [Группа], t.name, ROLLUP ((datepart (yyyy, OrderDate), datepart (mm, OrderDate)) |
Эта дополнительная скобка в предложении ROLLUP привела к ограничению агрегации только территорией и месяцем / годом.Оставьте их, и вы получите итоги за каждый год.
— получить итоги за каждый год в пределах каждой территории, а также итоги — для каждой территории — нет итогов для каждого региона ВЫБРАТЬ t. [Группа] AS регион, t.name AS территория , Sum (TotalDue) AS выручка, datepart (yyyy, OrderDate) AS [год], datepart (mm, OrderDate) AS [месяц] FROM Sales.SalesOrderHeader s INNER JOIN Sales.SalesTerritory T ON s.TerritoryID = T.TerritoryID GROUP BY t. [Group], t.name, ROLLUP (datepart (yyyy, OrderDate), datepart (mm, OrderDate)) |
Это может быть очень полезно для определенных данных. Мы избежали необходимости комбинировать столбцы здесь. Если бы вы сделали КУБ, и термины для территорий использовали бы такие слова, как «Северный» или «Южный» для описания территории в более чем одном регионе, у вас были бы некоторые причудливые агрегаты, применимые к «северным» территориям, которые не связаны между собой. .Комбинируя столбцы, вы избежите этого.
7. Может ли ГРУППИРОВАТЬ НАБОРЫ нечто большее, чем способ создания КУБОВ ‘à la carte’?
Не уверен, что стесняюсь задать этот вопрос. SQL: 1999 GROUPING SETS предоставляет богатый рекурсивный синтаксис, который позволяет агрегировать комбинации столбцов и определять все виды эзотерических отчетов, содержащих до десяти измерений. Агрегации могут быть вложенными, и вы можете вкладывать CUBE в ROLLUP и вкладывать ROLLUP в CUBE. Вам нужно будет прочитать специализированную публикацию, чтобы узнать больше об этом.
8. Почему предусмотрены функции
Grouping ()
и Grouping_ID () ?
Использование NULL для обозначения того, что столбец является агрегатом, — не лучшая идея. Проблема в том, что если группирующий столбец содержит значения NULL, все значения NULL считаются равными и помещаются в одну группу NULL, которая маскируется под сводку. Чтобы обойти очевидную трудность использования значений NULL в исходных данных, предусмотрены две функции: Grouping () и Grouping_ID ()
.
Функции Grouping ()
передается имя столбца, который участвовал в ROLLUP, CUBE или GROUPING SET. Он возвращает ноль, если эта строка является сводкой для этого столбца со значением NULL, означающим «все», или если она содержит значение.
Функции GROUPING_ID передается список, который должен точно соответствовать выражению в списке GROUP BY. GROUPING_ID создается как растровое изображение соответствующих итоговых столбцов. Если, например, в столбце территории есть NULL, означающее «все» территории, а не название территории, и он указан во втором столбце, то устанавливается второй слева бит.Затем возвращается это целое число.
Grouping_ID ()
обычно используется, чтобы указать, является ли строка первичной или вторичной агрегацией (0 или> 0) и, если она вторична, то исключена из любых дальнейших манипуляций GROUP BY.
Обычно считается хорошей практикой включать битовый столбец для каждого измерения (например, «Территория» или «Регион» в нашем примере), который устанавливается, если строка является сводкой для этого измерения, вместе с Grouping_ID ()
значение, чтобы облегчить дальнейшую группировку результата.
Чтобы проиллюстрировать, как на самом деле работает Grouping_ID, здесь мы рассмотрим способ установки битов в Grouping_ID в соответствии с типом сводки. Мы будем использовать функцию ToBinaryString Фила Фактора, чтобы показать биты.
SELECT t. [Группа] AS регион, t.name AS территория, сумма (TotalDue) AS выручка, datepart (yyyy, OrderDate) AS [год], datepart (mm, OrderDate) AS [месяц], правый ( dbo.ToBinaryString (- перечислить все группы по элементам, как они есть Grouping_ID (t. [Group], t.name, datepart (yyyy, OrderDate), datepart (mm, OrderDate)) ), 4) AS [Grouping Bitmap] — просто используйте последние четыре символа, так как в нашем списке четыре столбца. ОТ Sales.SalesOrderHeader s INNER JOIN Sales.SalesTerritory T ON s.TerritoryID = T.TerritoryID GROUP BY CUBE (т. [Группа], t.name, datepart (yyyy, OrderDate), datepart (mm, Дата заказа)) |
Это дает (конечно, только образец)…
Здесь интересно то, что каждая «1» в битовой карте группировки представляет соответствующий элемент группировки.В верхнем ряду есть тихоокеанский регион (0), все территории (1), все годы, (1), 12-й месяц (0). В последней строке указаны все регионы (1), Австралия (0), 2008 (0) и все месяцы (1). С помощью простых манипуляций с битами вы можете избежать работы с нулями!
Два способа объединения — IT Jungle
В трех мощных словах SQL я показал, как улучшить сводные запросы с помощью агрегированных значений по подмножествам группирующих столбцов. Сегодня я продолжу это обсуждение, показав два синтаксиса объединения и проиллюстрировав разницу между ними.
Во-первых, предположим, что есть таблица бухгалтерских операций.
выберите отдел, счет, сумму от xacts2 заказать по 1, 2 СУММА СЧЕТА ОТДЕЛА 1 10 200,00 1 10 250,00 1 30 300,00 2 10 125,00 2 20 175,00 2 20 225,00
Вот типичный сводный запрос с использованием знакомого предложения GROUP BY.
выберите отдел, счет, сумму (сумму) в качестве тамта от xacts2 группировать по отделам, аккаунтам заказать по 1,2 УЧЕТНАЯ ЗАПИСЬ ОТДЕЛА TAMT 1 10 450.00 1 30 300,00 2 10 125,00 2 20 400,00
Столбец суммы представлен двумя столбцами — отделом и счетом.
Чтобы добавить дополнительные совокупные итоги, просто добавьте WITH ROLLUP.
выберите отдел, счет, сумму (сумму) в качестве тамта от xacts2 группировать по отделам, аккаунтам со сверткой заказать по 1,2 УЧЕТНАЯ ЗАПИСЬ ОТДЕЛА TAMT 1 10 450.00 1 30 300,00 1 - 750,00 2 10 125,00 2 20 400,00 2 - 525,00 - - 1 275,00
Это дает мне общие и общие итоги по отделам.
Вот еще одна форма объединения, которая делает то же самое.
выберите отдел, счет, сумму (сумму) в качестве тамта от xacts2 группировать по свертке (отдел, аккаунт) заказать по 1,2 УЧЕТНАЯ ЗАПИСЬ ОТДЕЛА TAMT 1 10 450.00 1 30 300,00 1 - 750,00 2 10 125,00 2 20 400,00 2 - 525,00 - - 1 275,00
Итак, одна форма так же хороша, как другая? Рассмотрим следующие вопросы.
выберите отдел, счет, сумму (сумму) в качестве тамта от xacts2 группировать по свертке (отделу), аккаунту заказать по 1,2 УЧЕТНАЯ ЗАПИСЬ ОТДЕЛА TAMT 1 10 450.00 1 30 300,00 2 10 125,00 2 20 400,00 - 10 575,00 - 20 400,00 - 30 300,00
Обратите внимание, что есть агрегаты для счета, но не для отдела.
Вот еще один вариант.
выберите отдел, счет, сумму (сумму) в качестве тамта от xacts2 группировка по отделам, свертка (аккаунт) заказать по 1,2 УЧЕТНАЯ ЗАПИСЬ ОТДЕЛА TAMT 1 10 450.00 1 30 300,00 1 - 750,00 2 10 125,00 2 20 400,00 2 - 525,00
Здесь у нас есть сводные цифры по отделу, но не по счету.
Рассмотрим последний пример.
выберите отдел, счет, сумму (сумму) в качестве тамта от xacts2 группировать по свертке (отдел), свертке (аккаунт) заказать по 1,2 УЧЕТНАЯ ЗАПИСЬ ОТДЕЛА TAMT 1 10 450.00 1 30 300,00 1 - 750,00 2 10 125,00 2 20 400,00 2 - 525,00 - 10 575,00 - 20 400,00 - 30 300,00 - - 1 275,00
У нас есть итоги по отделам, итоги по счетам и общие итоги. Это эквивалентно WITH CUBE.
Какая форма лучше — GROUP BY ROLLUP или WITH ROLLUP? Вероятно, ГРУППА ПО РОЛИКЕ, по двум причинам:
1. Насколько я могу судить, GROUP BY ROLLUP кажется более стандартной и широко распространенной в мире реляционных баз данных, чем WITH ROLLUP.
2. Синтаксис GROUP BY ROLLUP позволяет нам создавать наборы результатов, которые мы не можем получить с помощью WITH ROLLUP.
По этим причинам я планирую уделить больше времени освоению нюансов синтаксиса GROUP BY ROLLUP.
РОДСТВЕННЫЕ ИСТОРИИ
Три мощных слова SQL
Сокровищница новых возможностей DB2 6.1, Часть 2: Группирующие наборы и супергруппы
Центр знаний IBM
Расширенное агрегирование, куб, группирование и сведение — Apache Hive
Этот документ описывает расширенные функции агрегирования для предложения GROUP BY операторов SELECT.
Версия
GROUPING__ID совместима с семантикой в других механизмах SQL, начиная с Hive 2.3.0 (см. HIVE-16102).
Поддержка группировки SQL Функция также была добавлена в Hive 2.3.0 (см. HIVE-15409).
Для получения общей информации о GROUP BY см. GroupBy в Руководстве по языку.
Предложение GROUPING SETS
Предложение GROUPING SETS в GROUP BY позволяет нам указать более одной опции GROUP BY в одном наборе записей. Все предложения GROUPING SET могут быть логически выражены в терминах нескольких запросов GROUP BY, связанных UNION.Таблица-1 показывает несколько таких эквивалентных утверждений. Это полезно при формировании идеи предложения GROUPING SETS. Пустой set () в предложении GROUPING SETS вычисляет общий агрегат.
Таблица 1 — Запросы GROUPING SET и эквивалентные запросы GROUP BY
Агрегированный запрос с GROUPING SETS | Эквивалентный агрегированный запрос с GROUP BY |
---|---|
SELECT (a, b, SUM c) FROM tab1 GROUP BY a, b НАБОРЫ ГРУППИРОВКИ ((a, b)) | SELECT a, b, SUM (c) FROM tab1 GROUP BY a, b |
SELECT a, b, SUM (c) FROM tab1 GROUP BY a, b НАБОРЫ ГРУППИРОВКИ ((a, b), a) | SELECT a, b, SUM (c) FROM tab1 GROUP BY a, b
SELECT a , null, SUM (c) FROM tab1 GROUP BY a |
SELECT a, b, SUM (c) FROM tab1 GROUP BY a, b GROUPING SETS (a, b) | SELECT a, null, SUM (c) FROM tab1 GROUP BY a
SELECT null, b, SUM (c) FROM tab1 GROUP BY b |
ВЫБРАТЬ a, b, СУММУ (c) ИЗ tab1 GROUP BY a, b НАБОРЫ ГРУППИРОВКИ ((a, b), a, b, ()) | SELECT a, b, SUM (c) FROM tab1 GROUP BY a, b
SELECT a, null, SUM (c) FROM tab1 GROUP BY a, null
SELECT null, b, SUM (c) FROM tab1 GROUP BY null, b
SELECT null, null, SUM (c) FROM tab1 |
Функция Grouping__ID
Когда агрегаты отображаются для столбца, его значение равно null.Это может привести к конфликту, если в самом столбце есть значения NULL. Должен быть способ идентифицировать NULL в столбце, что означает агрегирование, и NULL в столбце, что означает значение. Решением этой проблемы является функция GROUPING__ID.
Эта функция возвращает битовый вектор, соответствующий тому, присутствует ли каждый столбец или нет. Для каждого столбца создается значение «1» для строки в наборе результатов, если этот столбец был агрегирован в этой строке, в противном случае значение равно «0». Это можно использовать для различения, когда в данных есть нули.
Рассмотрим следующий пример:
Столбец 1 (ключ) | Столбец 2 (значение) |
---|---|
1 | NULL |
00 | |
2 | 2 |
3 | 3 |
3 | NULL |
4 0 |
Следующий запрос:
клавиша SELECT, значение, GROUPING__ID, count (*) ОТ Т1 GROUP BY ключ, значение WITH ROLLUP;
будет иметь следующие результаты:
Столбец 1 (ключ) | Столбец 2 (значение) | GROUPING__ID | 900 | NULL | NULL | 3 | 6 |
---|---|---|---|---|---|---|---|
1 | NULL | 1 | НОЛЬ | 0 | 1 | ||
1 | 1 | 0 | 1 | 0 | 1 | 1 | |
2 | 2 | 0 | 1 | ||||
3 | NULL | 1 | 2 | ||||
3 | NULL | 1 | |||||
3 | 3 | 0 | 1 | ||||
4 | NULL | 1 00 | |||||
4 | 5 | 0 | 1 |
Обратите внимание, что третий столбец представляет собой битовый вектор выбранных столбцов.
Для первой строки ни один столбец не выбран.
Для второй строки выбирается только первый столбец, что объясняет значение 1.
Для третьей строки выбираются оба столбца (а второй столбец оказывается пустым), что объясняет значение 0.
Функция группирования
Функция группирования указывает, агрегируется ли выражение в предложении GROUP BY для данной строки. Значение 0 представляет столбец, который является частью набора группировок, а значение 1 представляет столбец, который не является частью набора группировок.
Возвращаясь к нашему примеру выше, рассмотрим следующий запрос:
ключ SELECT, значение, GROUPING__ID, группировка (ключ, значение), группировка (значение, ключ), группировка (ключ), группировка (значение), считать(*) ОТ Т1 GROUP BY ключ, значение WITH ROLLUP;
Этот запрос даст следующие результаты.
Столбец 1 (ключ) | Столбец 2 (значение) | GROUPING__ID | группировка ключ) | группировка (ключ) | группировка (значение) | количество (*) | |
---|---|---|---|---|---|---|---|
NULL | NULL | 3 | 3 | 3 | 000 | 1 | 6 |
1 | NULL | 1 | 1 | 2 | 0 | 1 | 2 |
02 | NULL | 0 | 0 | 0 | 0 | 0 | 1 |
1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
2 | NULL | 920 920 900 | 0 | 1 | 1 | ||
2 | 2 | 0 | 0 | 0 | 0 | 0 | 900 3 | NULL | 1 | 1 | 2 | 0 | 1 | 2 |
3 | NULL | 0 | 0 | 0 | 1 | ||
3 | 3 | 0 | 0 | 0 | 0 | 1 | |
4 | NULL | 1 | 1 | 0 | 1 | 1 | |
4 | 5 | 0 | 0 | 0 | 0 | 0 | 1 |
9152 Кубы Общий синтаксис — WITH CUBE / ROLLUP.Он используется только с GROUP BY. CUBE создает промежуточный итог всех возможных комбинаций набора столбцов в своем аргументе. После того, как мы вычислим CUBE для набора измерений, мы сможем получить ответы на все возможные вопросы агрегирования по этим измерениям.
Здесь также стоит упомянуть, что
GROUP BY a, b, c WITH CUBE эквивалентно
GROUP BY a, b, c GROUPING SETS ((a, b, c), (a, b), (b , в), (а, в), (а), (б), (в), ()).
Предложение ROLLUP используется с GROUP BY для вычисления агрегата на уровнях иерархии измерения.
GROUP BY a, b, c с ROLLUP предполагает, что иерархия — это «a» с переходом вниз до «b» с переходом вниз до «c».
GROUP BY a, b, c, WITH ROLLUP эквивалентно GROUP BY a, b, c GROUPING SETS ((a, b, c), (a, b), (a), ()).
hive.new.job.grouping.set.cardinality
Следует ли запускать новое задание сокращения карты для группировки наборов / сверток / кубов.
Для такого запроса: выберите a, b, c, count (1) из группы T с помощью a, b, c с объединением;
В каждой строке создается 4 строки: (a, b, c), (a, b, null), (a, null, null), (null, null, null)
Это может привести к взрыву через границу уменьшения карты если мощность T очень высока
и агрегирование на стороне карты не очень хорошо работает.
Этот параметр определяет, должен ли куст добавить дополнительное задание уменьшения карты. Если количество элементов набора
группирования (4 в приведенном выше примере) больше, чем это значение, новое задание MR добавляется в соответствии с предположением
, что исходная группа по уменьшит размер данных.
Функция Grouping__ID (до Hive 2.3.0)
Функция Grouping__ID была исправлена в Hive 2.3.0, поэтому поведение до этого выпуска отличается (это ожидается). Для каждого столбца функция вернет значение «0», если этот столбец был агрегирован в этой строке, в противном случае значение равно «1».
Отсюда следующий запрос:
клавиша SELECT, значение, GROUPING__ID, count (*) ОТ Т1 GROUP BY ключ, значение WITH ROLLUP;
будет иметь следующие результаты.
NULL | NULL | 0 | 6 | |||
9000ULL2 1 | 9000ULL2 1 | 9000ULL2 1 | 9000ULL2 2 | |||
1 | NULL | 3 | 1 | |||
1 | 1 | 03 | 2 | NULL | 1 | 1 |
2 | 2 | 3 | 1 8 | 3 | 1 | 2 |
3 | NULL | 3 | 1 | |||
3 | 3 | 3 | 1 83 0 | NULL | 1 | 1 |
4 | 5 | 3 | 1 |
столбец
Обратите внимание, что бит-вектор выбранных столбцов.
Для первой строки ни один столбец не выбран.
Для второй строки выбирается только первый столбец, что объясняет счетчик 2.
Для третьей строки выбираются оба столбца (а второй столбец оказывается нулевым), что объясняет счетчик 1
Microsoft SQL Server — GROUP BY с ROLLUP и CUBE
Пример
Оператор ROLLUP полезен при создании отчетов, содержащих промежуточные и итоговые суммы.
CUBE создает набор результатов, который показывает агрегаты для всех комбинаций значений в выбранных столбцах.
ROLLUP создает набор результатов, который показывает агрегаты для иерархии значений в выбранных столбцах.
Артикул Цвет Кол-во Стол Синий 124 Стол Красный 223 Стул Синий 101 Стул Красный 210
ВЫБЕРИТЕ СЛУЧАЙ, КОГДА (ГРУППИРОВКА (Элемент) = 1) ТОГДА 'ВСЕ'
ELSE ISNULL (элемент; "НЕИЗВЕСТНО")
КОНЕЦ КАК Позиция,
СЛУЧАЙ, КОГДА (ГРУППИРОВКА (Цвет) = 1) ТОГДА 'ВСЕ'
ELSE ISNULL (цвет; 'НЕИЗВЕСТНО')
КОНЕЦ КАК Цвет,
SUM (количество) как QtySum
ИЗ инвентаря
ГРУППА ПО ПУНКТУ, Цвет В КОЛЛЕКЦИИ
Цвет товара Кол-во
-------------------- -------------------- ---------- ----------------
Стул Blue 101.00
Стул Красный 210.00
Стул ALL 311.00
Стол Синий 124.00
Стол Красный 223.00
Стол ВСЕ 347.00
ВСЕ ВСЕ 658.00
(затронуты 7 строк)
Если ключевое слово ROLLUP в запросе изменено на CUBE, набор результатов CUBE будет таким же, за исключением того, что эти две дополнительные строки возвращаются в конце:
ВСЕ Синий 225.00
ВСЕ Красный 433.00
https://technet.microsoft.com/en-us/library/ms189305(v=sql.90).aspx
Альтернатива функции SQL GROUP BY ROLLUP в Redshift
Последнее обновление от Vithal S
В других моих статьях мы обсуждали GROUP BY с GROUPING SETS и GROUP BY с альтернативами CUBE.В этой статье мы проверим функцию SQL GROUP BY ROLLUP, альтернативу в Amazon Redshift.
Реляционные базы данных, такие как Oracle, Teradata и т. Д., Поддерживают функцию GROUP BY ROLLUP для группировки строк результатов. Однако Amazon Redshift не поддерживает функцию GROUP BY ROLLUP.
SQL GROUP BY ROLLUP Альтернатива в Redshift
Подобно GROUP BY с CUBE, GROUP BY ROLLUP является расширением предложения GROUP BY, которое создает строки промежуточных итогов. Строки промежуточных итогов — это строки, которые дополнительно агрегируются, значения которых получены путем вычисления тех же агрегатных функций, которые использовались для создания сгруппированных строк.
Например, следующий запрос определяет предложение group by с функцией ROLLUP, которая включает pid и county. Это запрос Teradata, который будет выполняться без каких-либо проблем.
SELECT pid, county, SUM (продажа) как total_sale
ОТ sale_view
ГРУППА ПО РОЛИКЕ (пид, округ)
порядок по 1,2;
Ниже приведен вывод на сервере Teradata.
PID County total_sale
--- ------------- -----------
? ? 247350
1? 194225
1 Лос-Анджелес 111350
1 Сан-Диего Сан 82875
2? 53125
2 Лос-Анджелес 53125
Но тот же запрос с функцией ROLLUP не будет работать на сервере Amazon Redshift.При попытке выполнить вышеуказанный запрос вы получите « Недопустимая операция: набор функций (целое число, разные символы) не существует» «Ошибка в Redshift. Это потому, что Redshift не поддерживает функцию SQL GROUP BY ROLLUP.
Альтернатива функции GROUP BY ROLLUP с использованием UNION ALL
По сути, функция GROUP BY ROLLUP представляет собой комбинацию нескольких предложений GROUP BY. Результаты эквивалентны UNION ALL для указанных групп. Вы можете переписать исходный запрос, используя оператор набора UNION ALL Redshift, чтобы вернуть тот же набор результатов.
Например, следующий запрос объединяет несколько предложений GROUP BY для возврата строк промежуточной суммы.
выберите pid, county, SUM (sale) как total_sale
из sale_view
группа по пид, округ
СОЮЗ ВСЕ
выберите pid, null как округ, сумму (продажа) как total_sale
из sale_view
группа по pid
СОЮЗ ВСЕ
выберите NULL, NULL, сумма (продажа) как total_sale
из sale_view
порядок по 1,2;
Ниже приводится результат.
pid | округ | total_sale
----- + ------------- + ------------
1 | Лос-Анджелес | 111350
1 | Сан-Диего | 82875
1 | | 194225
2 | Лос-Анджелес | 53125
2 | | 53125
| | 247350
(6 рядов)
Обратите внимание, что пустое значение представляет NULL.
Обсуждаемый подход хорошо работает, если у вас есть предсказуемые столбцы в функции ROLLUP.
Статьи по теме,
Надеюсь, это поможет
SQL Server — TSQL — ГРУППА ПО С ROLLUP
GROUP BY группирует набор результатов в итоговые строки по предоставленным столбцам.Например, рассмотрим данные ниже, которые содержат данные о продажах по регионам.
Название группы Продажи, год выпуска
————————————- —————
Северная Америка Северо-запад 123237,00
Северная Америка Северо-запад 37534,00
Северная Америка Северо-запад 48003,00
Северная Америка Юго-запад 164232,00
Юго-восток Северной Америки 39667.00
Северная Америка Юго-восток 1058 10,00
Европа Франция 74569,00
Европа Германия 59456,00
Тихоокеанский регион Австралия 93403,00
Европа Великобритания 78327,00
Эти данные можно резюмировать с помощью предложения GROUP BY , как показано ниже:
— © 2011 — Vishal (http://SqlAndMe.com)
ВЫБЕРИТЕ [Группа], [Имя], СУММ ([SalesYTD]) КАК «Общий объем продаж»
ИЗ #TempTable
ГРУППА ПО [Группа], [Имя]
ЗАКАЗАТЬ [Группа], [Имя]
Результат набора:
Название группы Общий объем продаж
—————————————————–
Европа Франция 74569.00
Европа Германия 59456,00
Европа Великобритания 78327,00
Северная Америка Северо-запад 208774,00
Северная Америка Юго-восток 145477,00
Северная Америка Юго-запад 164232,00
Тихоокеанский регион Австралия 93403,00
(затронуты 7 строк)
В приведенном выше результате мы видим, что данные суммированы по [Группа] и [Имя].
С РОЛИКОМ:
ROLLUP можно использовать для создания строк промежуточных итогов и строк общего итога для строк агрегатов.
ВЫБЕРИТЕ [Группа], [Имя], СУММ ([SalesYTD]) КАК «Общий объем продаж»
ИЗ #TempTable
ГРУППА ПО [Группа], [Имя] С РОЛИКОМ
Результат набора:
Название группы Общий объем продаж
——————- ——————- ———————
Европа Франция 74569.00
Европа Германия 59456,00
Европа Великобритания 78327,00
Европа NULL 212352,00
Северная Америка Северо-запад 208774,00
Северная Америка Юго-восток 145477,00
Северная Америка Юго-запад 164232,00
Северная Америка NULL 518483,00
Тихоокеанская Австралия 93403.00
Pacific NULL 93403.00
NULL NULL 824238.00
(затронуты 11 строк)
Как мы видим в результирующем наборе, было добавлено 4 строки, по 3 для промежуточной суммы каждой [Группы] и 1 строка для общей суммы.
ГРУППИРОВКА ():
GROUPING () Функция может использоваться для проверки, агрегирована ли строка или нет.Он возвращает 1 для агрегированных строк.
— © 2011 — Vishal (http://SqlAndMe.com)
ВЫБЕРИТЕ [Группа], [Имя], СУММ ([SalesYTD]) КАК «Общий объем продаж»,
GROUPING ([Group]) AS ‘Aggregated’,
GROUPING ([Name]) AS ‘Aggregated’
ИЗ #TempTable
ГРУППА ПО [Группа], [Имя] С РОЛИКОМ
Результат набора:
Название группы Совокупный совокупный объем продаж
——————- ——————– ————- ————————
Европа Франция 74569.00 0 0
Европа Германия 59456,00 0 0
Европа Великобритания 78327,00 0 0
Европа NULL 212352,00 0 1
Северная Америка Северо-запад 208774,00 0 0
Северная Америка Юго-восток 145477,00 0 0
Северная Америка, юго-запад 164232.00 0 0
Северная Америка NULL 518483,00 0 1
Тихоокеанский регион Австралия 93403,00 0 0
Pacific NULL 93403.00 0 1
NULL NULL 824238.00 1 1
(затронуты 11 строк)
Наконец, мы можем использовать функцию GROUPING () для идентификации и замены «NULL» в агрегированных строках на что-то значимое.например «ВСЕ» !!!!.
ВЫБРАТЬ ГРУППУ СЛУЧАЙ ([Группа])
КОГДА 1 ТО «ВСЕ»
ELSE [Группа] END AS ‘Группа’,
ГРУППА СЛУЧАЙ ([Имя])
КОГДА 1 ТО «ВСЕ»
ELSE [Имя] КОНЕЦ КАК «Имя»,
SUM ([SalesYTD]) КАК «Общий объем продаж»
ИЗ #TempTable
ГРУППА ПО [Группа], [Имя] С РОЛИКОМ
Результат набора:
Название группы Общий объем продаж
————————————- ——————–
Европа Франция 74569.00
Европа Германия 59456,00
Европа Великобритания 78327,00
Европа ВСЕ 212352.00
Северная Америка Северо-запад 208774,00
Северная Америка Юго-восток 145477,00
Северная Америка Юго-запад 164232,00
Северная Америка ВСЕ 518483.