В версии SQL Server 2017 CTP2 не предусмотрены оконные агрегатные вычисления с ключевым словом DISTINCT в T-SQL. В данной статье рассматривается четыре способа обойти это ограничение.

T-SQL поддерживает сгруппированные агрегатные вычисления с ключевым словом DISTINCT, например COUNT (DISTINCT <выражение>), но в версии SQL Server 2017 CTP2 не поддерживаются оконные агрегатные вычисления, учитывающие только различные значения аргумента. На сайте Microsoft Connect есть открытый раздел (https://connect.microsoft.com/SQLServer/feedback/details/254393/over-clause-enhancement-request-distinct-clause-for-aggregate-functions), где обсуждается возможность ввода этой функции. Далее в статье я расскажу о том, что такое агрегатные вычисления с ключевым словом DISTINCT, приведу пример задачи, для которой требуются такие вычисления, покажу желательный, но отсутствующий синтаксис, который решил бы эту проблему, и представлю четыре поддерживаемых разработчиком обходных приема. Кроме того, мы рассмотрим тесты производительности для сравнения четырех решений, как с планами, использующими обработку только в построчном режиме, так и с планами с пакетным режимом обработки. В моих примерах используется тестовая база данных с именем TSQLV4. Сценарий для установки тестовой базы данных можно загрузить по адресу: tsql.solidq.com/SampleDatabases/TSQLV4.zip, а найти ER-диаграмму по адресу tsql.solidq.com/SampleDatabases/Diagrams/TSQLV4.jpg.

Задача и отсутствующий синтаксис

Как и в случае со сгруппированными агрегатными вычислениями с ключевым словом DISTINCT, оконные агрегатные вычисления с ключевым словом DISTINCT учитывают только уникальные вхождения аргумента. Но в отличие от сгруппированных вычислений, оконные вычисления не скрывают подробности. Например, предположим, что у нас есть таблица T1 с данными, показанными на экране 1.

 

Данные таблицы T1
Экран 1. Данные таблицы T1

Требуется вычислить для каждой строки как число различных значений (столбец val) в текущей группе (столбец grp), так и общее число различных значений. На экране 2 показан желаемый результат для приведенных тестовых данных.

 

Желаемый результат для тестовых данных
Экран 2. Желаемый результат для тестовых данных

Если бы оконные агрегатные вычисления с параметром DISTINCT поддерживались в T-SQL, эту задачу можно было бы решить так, как показано в листинге 1.

Примером практического применения таких вычислений может быть задача с таблицами Sales.Orders и Sales.OrderDetails в тестовой базе данных TSQLV4. В первой содержатся данные заголовка заказа, а в последней — данные строки заказа. Для нашей задачи важны столбцы orderid, orderdate и custid из таблицы Sales.Orders и столбцы orderid, productid, qty и unitprice из таблицы Sales.OrderDetails. Предположим, что клиенты получают скидки в зависимости от заказов, сделанных за предыдущий месяц, и нам нужно составить запрос для расчета этих скидок. Правила для начисления скидок приведены ниже.

  1. Процент скидки по номенклатуре рассчитывается так: 35% умножается на количество разных продуктов, заказанных клиентом в течение...
Это не вся статья. Полная версия доступна только подписчикам журнала. Пожалуйста, авторизуйтесь либо оформите подписку.

Поделитесь материалом с коллегами и друзьями

Купить номер с этой статьей в PDF