Получите самые высокие значения из itab для каждого другого значения в другом поле

Мне нужно получить строки с самыми высокими регистрами EXBEL из внутренней таблицы для каждого другого ВКОНТ.

Таблица результатов может содержать несколько строк для одного и того же значения ВКОНТ, если у этого последнего есть несколько строк в исходной таблице с одинаковым наибольшим значением EXBEL.

Фактическая исходная таблица:

SPARTE  VKONT         EXBEL
05      800000008422  1NSN150900000058
L2      800000008422  1NSN150900000058
05      800000008422  1NSN150900000037
L2      800000008422  1NSN150900000037
05      800000008422  1NSN150900000013
L2      800000008422  1NSN150900000013
05      800000008415  1HSN151200000009
S1      800000008415  1HSN151200000009
05      800000008415  1HSN151200000008
S1      800000008415  1HSN151200000008
L1      800000008422  1NSN150900000050
L1      800000008422  1NSN150900000029
L1      800000008422  1NSN150900000023
05      800000008415  1HSN151200000012
S1      800000008415  1HSN151200000012
05      800000008422  1NSN150900000058
L2      800000008422  1NSN150900000058
05      800000008415  1HSN151200000009
S1      800000008415  1HSN151200000009

Таблица ожидаемых результатов:

SPARTE  VKONT         EXBEL
05      800000008422  1NSN150900000058
L2      800000008422  1NSN150900000058
05      800000008415  1HSN151200000012
S1      800000008415  1HSN151200000012

Я пробовал разные решения, но не работал.

Любая помощь будет оценена.

Raúl.


person Raúl D.Martín    schedule 21.03.2019    source источник
comment
Пожалуйста, отредактируйте свой вопрос, чтобы уточнить значения, которые вы ожидаете. Кроме того, пожалуйста, прикрепите код, который вы пробовали (соответствующая часть), и объясните, что вы получили до сих пор. См. страницу Как спросить.   -  person Sandra Rossi    schedule 21.03.2019
comment
Я отредактировал ваш вопрос, чтобы уточнить его, пожалуйста, подтвердите, соответствует ли он вашему вопросу. Если нет, пожалуйста, отредактируйте его. Спасибо.   -  person Sandra Rossi    schedule 23.03.2019
comment
Спасибо Сандра. Да, это прекрасно объяснено.   -  person Raúl D.Martín    schedule 23.03.2019


Ответы (4)


Начиная с версии 7.52 вы можете выбрать для внутренних таблиц. Пример кода, как показано ниже.

TYPES:
BEGIN OF ty_s_value,
   sparte TYPE char2,
   vkont  TYPE char12,
   exbel  TYPE char16,
END OF ty_s_value.

TYPES:
ty_t_value TYPE STANDARD TABLE OF ty_s_value .

DATA:
  lt_value TYPE ty_t_value.

lt_value = VALUE #(
                    ( sparte = '05' vkont = '800008422' exbel = '0000000000000001')
                    ( sparte = 'l2' vkont = '800008422' exbel = '0000000000000002')
                    ( sparte = 'l2' vkont = '800008422' exbel = '0000000000000004')
                    ( sparte = '05' vkont = '800008423' exbel = '0000000000000003')
                    ( sparte = 'l2' vkont = '800008423' exbel = '0000000000000002')
                    ( sparte = 'l2' vkont = '800008423' exbel = '0000000000000005')
                 ).

SELECT FROM @lt_value AS a FIELDS a~sparte, a~vkont, MAX( a~exbel ) AS exbel 
   GROUP BY a~sparte, a~vkont
   ORDER BY a~sparte, a~vkont INTO TABLE @DATA(result).
person Haojie    schedule 22.03.2019
comment
Ничего себе, этот метод кажется очень простым и интуитивно понятным. К сожалению, я работаю с 740 версией SAP. - person Raúl D.Martín; 22.03.2019
comment
Это не только 7.52, это также зависит от базы данных и ее выпуска (допустимо для HANA 2.0, но не для Sybase ASE 16.0; это можно проверить во время выполнения методом USE_FEATURES класса CL_ABAP_DBFEATURES). Было бы интересно узнать тест производительности, я боюсь, что SELECT может быть очень медленным по сравнению с операторами ABAP. - person Sandra Rossi; 22.03.2019
comment
@SandraRossi согласно онлайн-справке только БД имеет значение, если ваш SELECT действительно использует БД, например, в JOIN. Почему и какое это имело бы значение, если бы он не использовался? - person András; 22.03.2019
comment
@ András András Я не знаю, почему это важно, но в моей системе 7.52 ASE приведенный выше код выполняет неподдерживаемое расширение базы данных CX_SY_SQL_UNSUPPORTED_FEATURE. Итак, о этом оператор не может быть выполнен на всех системах баз данных, если данные из внутренней таблицы необходимо передать в базу данных, вопрос КОГДА это нужно передать? - person Sandra Rossi; 22.03.2019
comment
@SandraRossi Я думаю, когда вы выполняете соединение, используя таблицу базы данных и внутреннюю таблицу - person Haojie; 23.03.2019
comment
@RaúlD.Martín oh.i придумает одно решение для 7.4 - person Haojie; 23.03.2019
comment
@Haojie Как я уже сказал, это не только в случае присоединения, ваш код не работает в моей системе 7.52 ASE; но это больше не сработает, если я удалю GROUP BY/ORDER BY. Я чувствую, что ограничения в некоторой степени связаны с ограничениями Буферизация таблиц, хотя это также зависит от системы базы данных. - person Sandra Rossi; 23.03.2019
comment
@ RaúlD.Martín, пожалуйста, проверьте мой новый ответ для 740. Спасибо! - person Haojie; 23.03.2019

Собрать в хешированную таблицу

Это работает с любой версией, поддерживаемой в настоящее время, быстрее2, чем SORT + DELETE ADJACENT DUPLICATES, и оставляет исходную таблицу нетронутой.

FIELD-SYMBOLS: <fs_itab> LIKE LINE OF lt_original.

DATA: ls_itab   LIKE LINE OF lt_original,
      lt_hashed TYPE HASHED TABLE OF itab WITH UNIQUE KEY vkont.

LOOP AT lt_original INTO ls_itab.
  READ TABLE lt_hashed ASSIGNING <fs_itab>
      WITH KEY vkont = ls_itab-vkont.
  IF sy-subrc = 0.
    IF ls_itab-exbel > <fs_itab>-exbel.
      <fs_itab>-exbel  = ls_itab-exbel.
      <fs_itab>-sparte = ls_itab-sparte.  "remove this if not needed"
    ENDIF.
  ELSE.
    INSERT ls_itab INTO TABLE lt_hashed.
  ENDIF.
ENDLOOP.

1) SORT + DAD имеет масштабирование скорости O (n * log (n)), в то время как это имеет O (n)

person András    schedule 22.03.2019
comment
Примечание для 1) Почему бы не использовать оператор COLLECT, так как он также использует (внутреннюю) хэш-таблицу? Это также будет более короткий код и, вероятно, будет быстрее, потому что это делается ядром (без интерпретации байт-кода ABAP). - person Sandra Rossi; 22.03.2019
comment
COLLECT не может найти MAX, только SUM. Так мы быстрее получим неверные значения - person András; 22.03.2019

Вы можете использовать SORT, за которым следует DELETE ADJACENT DUPLICATES, так как последний удалит все строки в определенных группах строк, кроме первой строки группы.

SORT itab BY vkont exbel DESCENDING. " Group by VKONT and put highest EXBEL in the group first
DELETE ADJACENT DUPLICATES FROM itab COMPARING VKONT.

Могут быть более эффективные способы, если вам нужно сохранить исходный itab нетронутым.

person Gert Beukema    schedule 21.03.2019
comment
Спасибо за ваш ответ, но с этим кодом я просто получаю 1 регистр на вконт, а не все регистры этого вконта, которые имеют такой же самый высокий эксбел. - person Raúl D.Martín; 22.03.2019

Вот решение REDUCE, оператор REDUCE доступен начиная с ABAP 7.40 SP08.

TYPES: BEGIN OF ty_s_value,
        sparte TYPE char2,
        vkont  TYPE char12,
        exbel  TYPE char16,
       END OF ty_s_value.
TYPES: ty_t_value TYPE STANDARD TABLE OF ty_s_value WITH EMPTY KEY.

DATA(lt_tab) = 
VALUE ty_t_value( 
                 ( sparte = '05' vkont = '800000008422' exbel = '1NSN150900000058')
                 ( sparte = 'L2' vkont = '800000008422' exbel = '1NSN150900000058')
                 ( sparte = '05' vkont = '800000008422' exbel = '1NSN150900000037')
                 ( sparte = 'L2' vkont = '800000008422' exbel = '1NSN150900000037')
                 ( sparte = '05' vkont = '800000008422' exbel = '1NSN150900000013')
                 ( sparte = 'L2' vkont = '800000008422' exbel = '1NSN150900000013')
                 ( sparte = '05' vkont = '800000008415' exbel = '1HSN151200000009')
                 ( sparte = 'S1' vkont = '800000008415' exbel = '1HSN151200000009')
                 ( sparte = '05' vkont = '800000008415' exbel = '1HSN151200000008')
                 ( sparte = 'S1' vkont = '800000008415' exbel = '1HSN151200000008')
                 ( sparte = 'L1' vkont = '800000008422' exbel = '1NSN150900000050')
                 ( sparte = 'L1' vkont = '800000008422' exbel = '1NSN150900000029')
                ...
                ).

DATA(lt_result) = 
VALUE ty_t_value( FOR GROUPS <group_key> OF <wa> IN lt_tab 
                  GROUP BY ( sparte = <wa>-sparte vkont = <wa>-vkont )
                  LET max2 = 
                  REDUCE #( INIT max = 
                            VALUE ty_s_value( )
                            FOR <m> IN GROUP <group_key>
                            NEXT max = COND #( WHEN <m>-exbel > max-exbel THEN <m> ELSE max ) )
                  IN ( max2 ) ).

Кстати, в вашем ожидаемом наборе результатов отсутствует строка L1, я предполагаю, что в своем выборе вы уважаете не только VKONT, но и SPARTE.

person Suncatcher    schedule 29.05.2019