Общие табличные выражения

Развитие языка ABAP в последнее время тесно связано с таким понятием как Code-To-Data, когда все расчёты принято выполнять на СУБД, а результатами пользоваться уже на сервере приложений. Основная причина такого перехода — развитие собственной СУБД HANA и более глубокая интеграция с её возможностями непосредственно в языке. Соответственно OpenSQL (или как сейчас принято называть ABAP SQL) постоянно расширяется новыми конструкциями языка, давая разработчикам все больше возможностей для переноса вычислений на СУБД.

Начиная с релиза ABAP 7.51 в языке стала доступна конструкция WITH позволяющая создавать подзапросы объединённые в рамках одного SQL выражения и использовать табличные результаты этих подзапросов для формирования общего результата. В какой-то степени конструкция WITH является более удобной альтернативой использованию глобальных временных таблиц и более быстрым вариантом нежели использование FOR ALL ENTRIES или нескольких последовательных запросов.

Далее на простом примере разберём как это работает.

Синтаксис

Общий синтаксис WITH выглядит следующим образом:

Выражение состоит из одного или более именнованного общего табличного выражения (Common table expression, далее CTE) и основного запроса, использующего одно или несколько общих выражений.

Символ «+» в начале каждого имени CTE является ключевым символом по аналогии с @ у ABAP переменных в SQL выражениях. После имени CTE опционально в скобках можно указать альтернативные имена для каждого выбранного в рамках CTE поля.

Каждый оператор WITH должен завершаться основным запросом (SELECT..), который использует по крайней мере один из своих CTE, и каждый CTE должен использоваться по крайней мере в одном последующем запросе. CTE не может использовать сам себя себя в качестве источника данных. WITH может использоваться как отдельный оператор или как дополнение в OPEN CURSOR.

ENDWITH — является аналогом ENDSELECT в случае если вы не выполняете запись во внутреннюю таблицу, а открываете цикл WITH, который необходимо закрыть с помощью ENDWITH. В отличие от SELECT..ENDSELECT нельзя использовать вложенные циклы.

Конструкция WITH пропускает буферизацию таблиц.

Примеры

Рассмотрим первый пример:

С помощью WITH мы создаём три подзапроса:

  • connections — где выбираем все записи из таблицы с рейсами SPFLI для выбранной авиакомпании;
  • sum_seats — где для авиакомпании и рейса считаем сумму занятых в полёте мест;
  • result — где создаём объединение двух предыдущих выборок и переименовываем поля для читаемости;

Финальный SELECT содержит уже конечную выборку из результатов полученных в подзапросах.

Для наглядности результаты промежуточных подзапросов и финального result:

Рассмотрим еще один пример:

Тут мы создали CTE cities как объединение двух подзапросов для поиска уникальных городов в таблице с рейсами из полей «город отправки» и «город прилёта».

Как видно из кода, основной SELECT не обязательно должен использовать CTE в качестве основного источника данных, в данном примере он используется как подзапрос. Важно лишь то, что каждый объявленный CTE должен быть использован.

Конструкцию WITH так же удобно использовать для формирования итоговых строк:

Динамическое использование

Как и при использовании оператора SELECT, допускается использование динамических конструкций:

Ограничения СУБД

При использовании конструкции WITH следует учитывать тот факт, что не все СУБД поддерживают полный перечень её возможностей. Так в подзапросах ограничение число записей и сортировка может быть недоступна на вашей СУБД, о чём вас предупредит расширенная проверка кода.

Производительность

Учитывая что выражение WITH целиком выполняется на уровне СУБД, скорость его работы будет выше нежели последовательное исполнение нескольких запросов или использование FOR ALL ENTRIES (даже на HANA с FDA), убедиться в этом можете запустив следующий пример:

Результат:

1 комментарий

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *