ROLLUP, CUBE и GROUPING SETS операторы Transact-SQL для подведения итогов и промежуточных итогов

В статье мы рассмотрим возможность Transact-SQL формировать отчеты, как со строкой общего итога, так и со строками промежуточных итогов, для этих целей в MS SQL Server существуют такие операторы как ROLLUP, CUBE и GROUPING SETS, именно о них мы сегодня и поговорим.

ROLLUP, CUBE и GROUPING SETS

Возможность построения отчетов на Transact-SQL очень полезная, мы с Вами уже об этом говорили, когда рассматривали оператор PIVOT, который может транспонировать набор данных, теперь давайте научимся писать запросы, в которых будут выделяться промежуточные итоги и итоги в целом. В Transact-SQL сделать это можно с помощью операторов ROLLUP, CUBE и GROUPING SETS.

Как Вы, наверное, догадываетесь, для того чтобы подсчитать итог или подытог, необходимо прибегнуть к агрегатным функциям и, соответственно, к группировке данных, поэтому операторы ROLLUP, CUBE и GROUPING SETS относятся к конструкции GROUP BY, т.е. являются расширением GROUP BY.

Эти операторы естественно отличаются друг от друга, поэтому в процессе рассмотрения мы будем их сравнивать, но для начала давайте определимся с тестовыми данными для примеров.

Исходные данные для примеров

В качестве SQL сервера у нас будет выступать Microsoft SQL Server Express 2014, а запросы будем писать в Management Studio Express.

Мы как всегда будем использовать выдуманные данные, и в этот раз я предлагаю вот такие, таблицу, которая будет содержать список сотрудников с указанием отдела, в котором они работают, а также сумму их заработка по годам.

Таблица

 
   CREATE TABLE [dbo].[test_table](
        [id] [INT] IDENTITY(1,1) NOT NULL,
        [manager] [VARCHAR](50) NULL,
        [otdel] [VARCHAR](50) NULL,
        [god] [INT] NULL,
        [summa] [MONEY] NULL
   ) ON [PRIMARY]
   GO

А данные вот такие

Скриншот 1

ROLLUP

ROLLUP – оператор Transact-SQL, который формирует промежуточные итоги для каждого указанного элемента и общий итог.

Для того чтобы понять, как работает данный оператор, предлагаю сразу перейти к примерам, и допустим, что нам необходимо получить сумму расхода на оплату труда по отделам и по годам, и сначала давайте попробуем написать запрос с группировкой без использования оператора ROLLUP.

Скриншот 2

   
   SELECT otdel, god, SUM(summa) AS itog 
   FROM dbo.test_table
   GROUP BY otdel, god
   ORDER BY otdel, god

Как видите, группировка у нас получилась и в принципе мы видим что, например, в бухгалтерии в 2014 был такой расход, а 2015 такой, но иногда руководство хочет видеть и общую информацию, например, общий расход по каждому отделу. Для этих целей мы можем использовать оператор ROLLUP.

Скриншот 3

Текст запроса

   
   SELECT otdel, god, SUM(summa) AS itog 
   FROM dbo.test_table
   GROUP BY 
   ROLLUP (otdel,god)

Строки со значением NULL и есть промежуточные итоги по отделам, а самая последняя строка общий итог. Согласитесь, что это уже более наглядно.

Можно также использовать rollup и с группировкой по одному полю, например:

Группировка по отделам с общим итогом

Скриншот 4

Группировка по годам с общим итогом

Скриншот 5

CUBE

CUBE — оператор Transact-SQL, который формирует результаты для всех возможных перекрестных вычислений.

Давайте напишем практически такой же SQL запрос, только вместо rollup укажем cube и посмотрим на полученный результат.

Скриншот 6

Текст запроса

   
   SELECT otdel, god, SUM(summa) AS itog 
   FROM dbo.test_table
   GROUP BY 
   CUBE (otdel,god)

В данном случае отличие от rollup заключается в том, что группировка и промежуточные итоги выполнены как для otdel, так и для god.

GROUPING SETS

GROUPING SETS – оператор Transact-SQL, который формирует результаты нескольких группировок в один набор данных, другими словами, он эквивалентен конструкции UNION ALL к указанным группам.

Пример GROUPING SETS

Скриншот 7

Текст запроса

   
   SELECT otdel, god, SUM(summa) AS itog 
   FROM dbo.test_table
   GROUP BY
   GROUPING SETS (otdel,god)

тот же результат, но с использованием UNION ALL

Скриншот 8

Текст запроса

   
   SELECT null AS otdel, god, SUM(summa) AS itog 
   FROM dbo.test_table
   GROUP BY god

   UNION ALL

   SELECT otdel, null AS god, SUM(summa) AS itog 
   FROM dbo.test_table
   GROUP BY otdel

А сейчас предлагаю поговорить еще об одной полезной возможности, которая напрямую относится к перечисленным выше операторам, а именно о функции GROUPING.

GROUPING – функция Transact-SQL, которая возвращает истину, если указанное выражение является статистическим, и ложь, если выражение нестатистическое.

Данная функция создана для того, чтобы отличить статистические строки, которые добавил SQL сервер, от строк, которые и есть сами данные, так как когда используешь много группировок, запутаться в строках очень легко.

Пример GROUPING

Скриншот 9

Текст запроса

   
   SELECT otdel,
          ISNULL(CAST(god AS VARCHAR(30)), 
                 CASE WHEN GROUPING(god)=1 ANS GROUPING(otdel)=0 
                      THEN 'Промежуточный итог' 
                      ELSE 'Общий итог' END) AS god,
          SUM(summa) AS itog,
          GROUPING(otdel) AS grouping_otdel,
          GROUPING(god) AS grouping_god
   FROM dbo.test_table
   GROUP BY 
   ROLLUP (otdel,god)

На этом все, надеюсь, что возможность формировать итоги и промежуточные итоги в Microsoft SQL Server Вам будет полезна. Также рекомендую Вам почитать мою книгу «Путь программиста T-SQL. Самоучитель по языку Transact-SQL» в ней я подробно, с большим количеством примеров, рассказываю про основы языка Transact-SQL специально для начинающих. Удачи!

Понравилась статья? Поделиться с друзьями:
Заметки IT специалиста
Комментарии: 1
  1. Аватар
    Юрий

    А возможно ли сделать подИтог без подИтогов групп. Только одну строка чтобы была отображена в конце таблицы? Но без использования UNION ALL

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:
Нажимая на кнопку «Отправить комментарий», я даю согласие на обработку персональных данных и принимаю политику конфиденциальности.