1
votes

Obtenez les valeurs les plus élevées d'un itab pour chaque valeur différente dans un autre champ

J'ai besoin d'obtenir les lignes avec les registres EXBEL les plus élevés à partir d'une table interne pour chaque VKONT différent .

La table de résultats peut contenir plusieurs lignes pour le même Valeur VKONT si cette dernière a plusieurs lignes dans la table source avec la même valeur EXBEL la plus élevée.

Table source réelle:

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

Table de résultats attendus:

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

J'ai essayé différentes solutions mais je n'ai pas fonctionné.

Toute aide sera appréciée.

Raúl. p >


3 commentaires

Veuillez modifier votre question pour clarifier les valeurs que vous attendez. De plus, veuillez joindre le code que vous avez essayé (partie pertinente) et expliquer ce que vous avez obtenu jusqu'à présent. Consultez la page Comment demander .


J'ai édité votre question pour la clarifier, veuillez confirmer si elle correspond à votre question. Si non, veuillez le modifier. Merci.


Merci Sandra. Oui, c'est parfaitement expliqué.


4 Réponses :


1
votes

Vous pouvez utiliser un TRIER suivi d'un DELETE ADJACENT DUPLICATES car ce dernier supprimera toutes les lignes de certains groupes de lignes, à l'exception de la première ligne du groupe.

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

Il pourrait y avoir des moyens plus efficaces si vous avez besoin de conserver le itab original intact.


1 commentaires

Merci pour votre réponse, mais avec ce code, je reçois juste 1 registre par vkont, au lieu de tous les registres de ce vkont qui ont le même exbel le plus élevé.



4
votes

À partir de 7.52, vous pouvez sélectionnez sur les tables internes. Exemple de code comme ci-dessous.

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).


8 commentaires

Wow, cette méthode est super simple et intuitive. Malheureusement, je travaille avec la version 740 SAP.


Ce n'est pas seulement 7.52, cela dépend aussi de la base de données et de sa version (OK pour HANA 2.0, mais pas pour Sybase ASE 16.0; il peut être vérifié à l'exécution avec la méthode USE_FEATURES de la classe CL_ABAP_DBFEATURES). Un benchmark de performance serait intéressant à connaître, je crains que SELECT ne soit très lent par rapport aux déclarations ABAP.


@SandraRossi selon l ' aide en ligne la base de données uniquement importe si votre SELECT utilise également la base de données, comme dans un JOIN. Pourquoi et en quoi est-ce important s'il n'est pas utilisé?


@ András Je ne sais pas pourquoi c'est important mais sur mon système 7.52 ASE, le code ci-dessus fait un CX_SY_SQL_UNSUPPORTED_FEATURE "Extension de base de données non prise en charge". Donc, à propos de " Cette instruction ne peut pas être exécutée sur tous les systèmes de base de données, si les données de la table interne doivent être transmises à la base de données ", la question est QUAND doit-elle être transmise?


@SandraRossi Je suppose que lorsque vous faites une jointure en utilisant une table de base de données et une table interne


@ RaúlD.Martín oh.i proposera une solution pour 7.4


@Haojie Comme je l'ai dit, ce n'est pas seulement en cas de jointure, votre code échoue sur mon système 7.52 ASE; mais cela n'échoue plus si je supprime le GROUP BY / ORDER BY. Je pense que les restrictions sont quelque peu liées à celles de Table Buffering , bien que cela dépende également du système de base de données.


@ RaúlD.Martín s'il vous plaît vérifier ma nouvelle réponse pour 740. Merci!



2
votes

Rassembler vers une table hachée

Cela fonctionne avec n'importe quelle version actuellement prise en charge, est plus rapide 2 qu'un TRIER + SUPPRIMER LES DUPLICATS ADJACENTS, et laisse la table d'origine intacte.

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 a une échelle de vitesse de O (n * log (n)), alors que celle-ci a O (n)


2 commentaires

Remarque pour 1) Pourquoi ne pas utiliser l'instruction COLLECT car elle utilise également une table hachée (interne)? Ce serait aussi un code plus court, et ce serait probablement plus rapide car c'est fait par le noyau (pas d'interprétation de code d'octet ABAP).


COLLECT ne trouve pas MAX, seulement SUM. Nous obtenons donc les mauvaises valeurs plus rapidement



0
votes

Voici la solution REDUCE, l'opérateur REDUCE est disponible depuis 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 ) ).

BTW, votre jeu de résultats attendu manque la ligne L1, je suppose que dans votre sélection vous respectez non seulement VKONT mais SPARTE aussi.


0 commentaires