Экстремальные значения в каждой группе набора данных

У меня есть запрос 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: введите здесь описание изображения

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

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


person Pavan Kumar Polavarapu    schedule 03.10.2019    source источник
comment
Что такое промежуточные записи? Покажите их на ваших примерах данных   -  person Suncatcher    schedule 04.10.2019
comment
Данные уже включены в вопрос, и позвольте мне поделиться контекстом. Контракты создаются каждый раз, но нас интересуют только первый контракт и последний контракт. Контрактов может быть 100, но важны только первый и последний. На данный момент я написал Union с Inner Selects для максимальных и минимальных дат, но хотел бы знать другие подходы.   -  person Pavan Kumar Polavarapu    schedule 04.10.2019


Ответы (2)


У вас уже есть оптимальное решение с подзапросами.

Псевдокод:

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 не будет работать, так как он «перепутает» минимумы в разных столбцах.

Приятным штрихом может быть извлечение подвыборок в собственные представления, например. EarlyestContractPerPob и LatestContractPerPob.

person Florian    schedule 04.10.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). strong>) для первого и последнего.

------------------------------------------------
|        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 = последний):

введите здесь описание изображения

Ваш 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.

person Suncatcher    schedule 27.10.2019