Экстремальные значения в каждой группе для сгруппированного набора данных в ABAP CDS - PullRequest
1 голос
/ 03 октября 2019

У меня есть запрос SQLScript, написанный на AMDP, который создает два новых столбца source_contract и target_contract.

RETURN SELECT client as client,
    pob_id as pob_id,
    dateto as change_to,
    datefrom as change_from,
    cast( cast( substring( cast( datefrom as char( 8 ) ), 1,4 ) as NUMBER ( 4 ) ) as INT )
        as change_year,
    cast( CONCAT( '0' , ( substring( cast( datefrom as char( 8 ) ), 5,2  ) ) ) as VARCHAR (3))
        as change_period,
    LAG( contract_id, 1, '00000000000000' ) OVER ( PARTITION BY pob_id ORDER BY pob_id, datefrom )
        as source_contract,
    contract_id as target_contract
    from  farr_d_pob_his
    ORDER BY pob_id

Исходные данные:

POB     Valid To    Valid From  Contract
257147  05.04.2018  05.04.2018  10002718
257147  29.05.2018  06.04.2018  10002719
257147  31.12.9999  30.05.2018  10002239

Данные из представления AMDP:enter image description here

Я хочу игнорировать любые промежуточные строки (дата является критерием для определения порядка). Любое предложение или идеи?

Я думал об использовании Group by, чтобы получить максимальную дату и минимальную дату, и об объединении этих записей в отдельном представлении потребления, но если мы используем group by, мы не можем получитьдругие записи. Другая возможность - это заказ по дате, но она не доступна в CDS.

Ответы [ 2 ]

0 голосов
/ 27 октября 2019

Вот пример концепции решения вашей задачи.

При условии, что мы предварительно выбрали набор данных типа материала ( MTART ) на основе таблицы mara, которая являетсяочень похоже на ваше:

------------------------------------------------
|        MATNR     |   ERSDA  |   VPSTA  |MTART|
------------------------------------------------
|       17000000007|18.06.2018|KEDBXCZ   |ZSHD |
|       17000000008|21.06.2018|K         |ZSHD |
|       17000000011|21.06.2018|K         |ZSHD |
|       17000000023|22.06.2018|KEDCBGXZLV|ZSHD |  
|       17000000103|09.01.2019|K         |ZSHD |
|       17000000104|09.01.2019|K         |ZSHD |
|       17000000105|09.01.2019|K         |ZSHD |
|       17000000113|06.02.2019|V         |ZSHD |
------------------------------------------------

Вот материалы, и мы хотим оставить только последний и первый материал ( MATNR ) по дате создания ( ERSDA ) и найдите тип обслуживания ( VPSTA ) для первого и последнего из них.

------------------------------------------------
|        MATNR     |   ERSDA  |   VPSTA  |MTART|
------------------------------------------------
|       17000000007|18.06.2018|KEDBXCZ   |ZSHD |
|       17000000113|06.02.2019|V         |ZSHD |
------------------------------------------------

В вашем случае аналогичным образом выполняйте поиск в каждом POB (mtart) источникеи целевые контракты contract_id (последний и первый vpsta) на основе критерия datefrom (ersda).

Этого можно достичь, используя UNIONи два выбора с подзапросами:

 SELECT ersda AS date, matnr AS max, mtart AS type, vpsta AS maint
   FROM mara AS m
  WHERE ersda = ( SELECT MAX( ersda ) FROM mara WHERE mtart = m~mtart )
    UNION SELECT ersda AS date, matnr AS max, mtart AS type, vpsta AS maint
     FROM mara AS m2
    WHERE ersda = ( SELECT MIN( ersda ) FROM mara WHERE mtart = m2~mtart )
    ORDER BY type, date
     INTO TABLE @DATA(lt_result).

Здесь вы можете заметить, что первые выборки выбирают максимум ersda дат, а второй выбор выбирает минимальные.

Результирующий набор упорядочен по типуи дата будет в некоторой степени то, что вы ищете (F = первый, L = последний):

enter image description here

Ваш SELECT должен выглядеть примерно так:

 SELECT datefrom as change_from, contract_id AS contract, pob_id AS pob
   FROM farr_d_pob_his AS farr
  WHERE datefrom = ( SELECT MAX( datefrom ) FROM farr_d_pob_his WHERE pob_id = farr~pob_id )
    UNION SELECT datefrom as change_from, contract_id AS contract, pob_id AS pob
     FROM farr_d_pob_his AS farr2
    WHERE datefrom = ( SELECT MIN( datefrom ) FROM farr_d_pob_his WHERE pob_id = farr2~pob_id )
    ORDER BY pob, date
     INTO TABLE @DATA(lt_result).

Обратите внимание, это будет работать только в том случае, если у вас есть уникальные datefrom даты, в противном случае запрос не будет знать, какие последние / первыеконтракт, который вы хотите использовать. Кроме того, в случае только одного контракта в каждом POB будет только одна запись.

Пару слов о реализации. В вашем примере я вижу, что вы используете класс AMDP, но позже вы упомянули, что ORDER не поддерживается CDS. Да, они не поддерживаются в CDS, а также в подзапросах, но они поддерживаются в AMDP.

Следует различать два типа функций AMDP : функции для метода AMDP и функции дляТабличные функции CDS. Первые отлично обрабатывают SELECT с сортировкой и подзапросами. Вы можете просмотреть примеры в демонстрационном классе CL_DEMO_AMDP_VS_OPEN_SQL, который демонстрирует функции AMDP, включая подзапросы. Вы можете получить свой код в функции AMDP и вызвать его из реализации табличной функции CDS.

0 голосов
/ 04 октября 2019

У вас уже есть оптимальное решение с вложенными выборками.

Псевдокод:

SELECT *
  FROM OriginalData
  WHERE (POB, ValidFrom)
     IN (SELECT POB, MIN(ValidFrom)
          FROM OriginalData
          GROUP BY POB)
    OR (POB, ValidTo)
     IN (SELECT POB, MAX(ValidTo)
           FROM OriginalData
           GROUP BY POB);

GROUP BY не будет работать, так как он «перемешивает» минимумы в разных столбцах.

Приятным прикосновением может быть выделение вложенных элементов в собственные представления, например. Самый ранний КонтрактПер и ПоследнийКонтрПер.

...