Skip to content

Агрегирующие функции в подзапросах ABAP SQL

OlegBash599 edited this page Jan 17, 2024 · 12 revisions

Пусть у нас есть следующая модель данных (прообраз сбытовых VBAK-VBAP-BUT000).

Структура таблицы ZSLS_ORD_H

Поле Тип Комментарий
ID_NUM CHAR(10) Номер заказа, Ключ
PARTNER CHAR(10) ID-клиента
NUM_EXT CHAR(35) Внешний номер заказа

Структура таблицы ZSLS_ORD_I

Поле Тип Комментарий
ID_NUM CHAR(10) Номер заказа, Ключ
ITEM_NUM CHAR(10) Номер позиции, Ключ
PROD_ID Номер продукта
PRICE Цена
QUAN Кол-во
UOM Единица измерения

Структура таблицы ZPARTNER_H

Поле Тип Комментарий
PARTNER CHAR(10) ID-клиента, Ключ
PARTNER_NAME CHAR(200) Наименование клиента
Таблицы заполнены с помощью метода ниже.
  METHOD _prepare_tabs.

    DATA lt_ord_h TYPE STANDARD TABLE OF zsls_ord_h.
    DATA lt_ord_i TYPE STANDARD TABLE OF zsls_ord_i.
    DATA lt_partner_h TYPE STANDARD TABLE OF zpartner_h.

    lt_ord_h = VALUE #(
    ( id_num = '1001' partner = '2001' num_ext = 'EXT_NUM_FOR_1001' )
    ( id_num = '1002' partner = '2002' num_ext = 'EXT_NUM_FOR_1002' )
    ( id_num = '1003' partner = '2003' num_ext = 'EXT_NUM_FOR_1003' ) ).

    lt_ord_i = VALUE #(
    ( id_num = '1001' item_num = '1' prod_id = 'PRODUCT_91' price = '20'
        quan = 5  uom = 'PC' total = 100 waers = 'RUB' )
    ( id_num = '1001' item_num = '2' prod_id = 'PRODUCT_92' price = '25'
        quan = 6  uom = 'PC' total = 150 waers = 'RUB' )
    ( id_num = '1001' item_num = '3' prod_id = 'PRODUCT_93' price = '15'
        quan = 7  uom = 'PC' total = 105 waers = 'RUB' )

    ( id_num = '1002' item_num = '1' prod_id = 'PRODUCT_81' price = '20'
        quan = 3  uom = 'PC' total = 60 waers = 'RUB' )
    ( id_num = '1002' item_num = '2' prod_id = 'PRODUCT_82' price = '30'
        quan = 8  uom = 'PC' total = 240 waers = 'RUB' )
    ( id_num = '1002' item_num = '3' prod_id = 'PRODUCT_83' price = '40'
        quan = 4  uom = 'PC' total = 120 waers = 'RUB' )

    ( id_num = '1003' item_num = '1' prod_id = 'PRODUCT_71' price = '33'
        quan = 7  uom = 'PC' total = 231 waers = 'RUB' )
    ( id_num = '1003' item_num = '2' prod_id = 'PRODUCT_72' price = '23'
        quan = 15  uom = 'PC' total = 345 waers = 'RUB' )
    ).

    lt_partner_h = VALUE #(
     ( partner = '2001' partner_name = 'ООО Полезное оборудование' )
     ( partner = '2002' partner_name = 'ЗАО Тюльпанчик' )
     ( partner = '2003' partner_name = 'ПАО Простоцарский банк' )
    ).

    MODIFY zsls_ord_h FROM TABLE lt_ord_h.
    MODIFY zsls_ord_i FROM TABLE lt_ord_i.
    MODIFY zpartner_h FROM TABLE lt_partner_h.

    COMMIT WORK.

  ENDMETHOD.

Нужно вывести список заказов с позицией с номер позиции с наибольшей суммой, наибольшую сумму, наименьшую сумму и наименование клиента.

Набор полей, которые требуется отобразить.
TYPES: BEGIN OF ts_res
        , id_num TYPE zsls_ord_h-id_num
        , item_num TYPE zsls_ord_i-item_num
        , partner_name TYPE zpartner_h-partner_name
        , total_max TYPE zsls_ord_i-total
        , total_min TYPE zsls_ord_i-total
      , END OF ts_res
      , tt_res TYPE STANDARD TABLE OF ts_res WITH DEFAULT KEY
      .

Решение этой задачи средствами ABAP SQL будет зависеть от версии система.

Версия ABAP до 752. До версии 752 у нас есть возможность в подзапросах использовать скалярные значения других запросов. В данном случае в подзапросе вычислим максимальное и минимальное значения и укажем их в условии WHERE.
[Доступно с версии 4.7](https://help.sap.com/saphelp_470/helpdata/EN/fc/eb39c4358411d1829f0000e829fbfe/frameset.htm)
    DATA lt_res TYPE tt_res.

    " доступно с 4.7
    " https://help.sap.com/saphelp_470/helpdata/EN/fc/eb39c4358411d1829f0000e829fbfe/frameset.htm
    " в подзапросе возвращается скалярное выражение и
    " и его используем как значение для общего JOIN
    SELECT h~id_num  imax~item_num k~partner_name imax~total as total_max imin~total as total_min
      FROM zsls_ord_i AS imax JOIN zsls_ord_h AS h ON imax~id_num EQ h~id_num
       join zsls_ord_i AS imin ON imin~id_num EQ imax~id_num
        JOIN zpartner_h AS k ON h~partner EQ k~partner
      INTO TABLE lt_res
      WHERE
       imax~total EQ (
        SELECT MAX( total ) FROM zsls_ord_i WHERE id_num EQ h~id_num
      )
      and
      imin~total EQ (
        SELECT MIN( total ) FROM zsls_ord_i WHERE id_num EQ h~id_num
      )
      ORDER BY h~id_num  imax~item_num
      .
Версия 752 и выше (доступны Common Table Expressions).
    " Используем CTE для формирования подзапросов
    " https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/index.htm?file=abapwith_subquery.htm
    WITH +ord_item_subtot AS (
      SELECT h~id_num AS ord_num, MAX( i~total ) AS maxtotal_item, MIN( i~total ) AS mintotal_item
        FROM zsls_ord_h AS h JOIN zsls_ord_i AS i ON h~id_num EQ i~id_num
        GROUP BY h~id_num
    )

    SELECT h~id_num, i~item_num, k~partner_name, subtot~maxtotal_item, subtot~mintotal_item
      FROM zsls_ord_i AS i JOIN zsls_ord_h AS h
        ON i~id_num EQ h~id_num
        JOIN +ord_item_subtot AS subtot ON i~id_num EQ subtot~ord_num and i~total = subtot~maxtotal_item
        JOIN zpartner_h AS k ON h~partner EQ k~partner
      ORDER BY h~id_num
      INTO TABLE @lt_res
      .

В качестве результата получим таким значения в данном случае. output_pict1

Полный код-листинг демо-отчета доступен по ссылке.

Clone this wiki locally