4
votes

Rechercher le dernier résultat correspondant en utilisant "lire la table avec la clé"

J'ai besoin de trouver le sy-tabix d'une dernière entrée dans une table interne qui correspond à v_key = x. J'essaie de le faire avec:

read table i_tab with key v_key = x

Mais comme il y a plusieurs entrées dans le tableau qui correspondent à v_key = x, comment puis-je m'assurer d'obtenir le sy-tabix de la dernière correspondance entrée? Je ne peux malheureusement pas rechercher par une autre clé.


1 commentaires

Deux possibilités: Soit utiliser LOOP AT ... WHERE v_key = x, SY-TABIX à l'intérieur de la boucle à la dernière itération vous donnera le numéro de ligne. Ou calculez la prochaine valeur possible de x au niveau de l'octet (octet + 1), triez votre table (de préférence à une table avec une clé triée), faites un READ TABLE avec "X + 1", qui renverra SY-TABIX de la ligne suivante, alors soustrayez simplement 1.


5 Réponses :


6
votes

LIRE LA TABLE est pour lire des lignes simples, pour plus de lignes, vous devez utiliser LOOP:

LOOP AT itab
     ASSIGNING ...
     WHERE vkey EQ x.
ENDLOOP.

Juste après le LOOP sy-tabix contiendra la dernière ligne, où la condition est vraie.

Comme il a été indiqué (voir la discussion ci-dessous), pour les meilleures performances, il doit exister un Clé triée NON UNIQUE (principale ou secondaire) pour ce champ


6 commentaires

Cela fonctionne, mais semble devenir assez lent en fonction de la taille de la table. N'y a-t-il pas une méthode plus rapide?


@suimon, cf mon commentaire, 2ème possibilité.


@SandraRossi Je n'ai même pas une idée de ce que c'est ou comment ça marche: / Mais merci, je vais sur Google!


@suimon cf commentaire converti en réponse avec addendum pour fournir plus de détails


bien sûr, avec LOOP AT, itab doit être une table déclarée TYPE TRIÉ TABLE DE ... AVEC CLÉ NON UNIQUE v_key pour une performance optimale. De plus, si vous avez plusieurs lignes avec la même valeur v_key, alors les performances ne sont pas optimales (cf ma réponse pour une meilleure approche)


@JozsefSzikszai vaut peut-être la peine d'ajouter une remarque sur les performances directement dans votre réponse.



1
votes

Je pense que le moyen le plus rapide est

Sort itab by key.
read table itab with key key = v_key
                binary search.
loop at itab assign <fs> from sy-tabix.
   if <fs>-key ne v_key.
      exit.
   endif.
endloop.


1 commentaires

Pourquoi ne pas utiliser un index trié (clé primaire ou secondaire) pour que votre code ait les mêmes performances, mais soit plus petit (identique au code affiché par @JozsefSzikszai)



2
votes

Une autre possibilité, qui est utile si vous avez plusieurs lignes avec la même valeur v_key.

D'abord, assurez-vous qu'une ligne existe pour X. Si elle n'est pas trouvée, alors pas besoin de poursuivre.

Calculez la prochaine valeur possible (variable x_next_value) de la valeur recherchée (variable X). Exemples:

  • Si X est un entier, recherchez simplement X + 1. Exemple: pour la valeur 5, x_next_value sera 6.
  • Si X sont des caractères (C ou chaîne), alors obtenez le numéro du dernier caractère ( cl_abap_conv _ ** out ** _ ce => uccpi ), ajoutez 1 et mettez à jour le dernier caractère ( cl_abap_conv _ ** in ** _ ce => uccpi ).
  • Même type de logique pour les autres types de X.

Assurez-vous que votre table est triée (de préférence à une table déclarée table triée de ... avec une clé non unique v_key )

Alors faites LIRE LE TABLEAU itab AVEC CLÉ v_key = x_next_value .

Important : même si aucune ligne n'est trouvée, SY-TABIX sera mis au numéro de la ligne suivante après toutes les lignes ayant v_key = x (cf Documentation ABAP de READ TABLE - Valeurs possibles pour SY-SUBRC et SY-TABIX )

Pseudo code:

READ TABLE ... WITH KEY v_key = x_next_value.
" eventually BINARY SEARCH if itab is STANDARD instead of SORTED

CASE sy-subrc.
  WHEN 0.
    last_tabix_of_x = sy-tabix.
  WHEN 4.
    last_tabix_of_x = sy-tabix - 1.
  WHEN 8.
    last_tabix_of_x = lines( itab ).
ENDCASE.

Remarque: exactement deux READ TABLE sont nécessaires pour trouver le dernier résultat correspondant.


2 commentaires

cela ne fonctionne pas si la clé n'est pas une séquence, si la table a des clés (1,3, 8, 10), un simple ajout de 1 à la clé échouera.


@ I.B.N. Dans votre exemple, la recherche de "9" fera échouer READ TABLE "avec SY-SUBRC = 4 mais en même temps SY-TABIX est mis à 4 (pointez sur la ligne "10"), car c'est la ligne avec une valeur juste au-dessus de "9" - cf Documentation ABAP de READ TABLE - Valeurs possibles pour SY-SUBRC et SY-TABIX



0
votes

J'écris une solution différente qui pourrait vous être utile.

ajoutez une colonne keyno dans la table i_tab.

Lorsque vous insérez des enregistrements dans la table i_tab, et qu'il y a plusieurs enregistrements à ajouter dans la table i_tab pour la même clé, vous pouvez ajouter keyno pour chaque enregistrement où la même clé a plusieurs enregistrements.

Par exemple:

Insertion d'enregistrements dans la table i_tab

   read table i_tab with key = X

Tableau i_tab Tri par clé Keyno décroissant .

   SORT i_tab by key keyno Desc.

Maintenant, Read Table va trouver la dernière entrée correspondante de la table i_tab pour la clé.

i_tab_line-key = 'X'.
i_tab_line-keyno = 1.
APPEND i_tab_line to i_tab.
i_tab_line-key = 'X'.
i_tab_line-keyno = 2.
APPEND i_tab_line to i_tab.
i_tab_line-key = 'X'.
i_tab_line-keyno = 3.
APPEND i_tab_line to i_tab.

salutations,

Umar Abdullah


1 commentaires

Et si OP ne remplit pas cette table et ne peut pas ajouter son propre champ?



-1
votes
sort i_tab by v_key .
read table i_tab with key v_key = x binary search.

while i_tab-key = x
  lv_tabix = sy-tabix + 1 .
  read table i_tab index = lv_tabix .
endwhile.

result = lv_tabix -1 .

5 commentaires

tu as raison, ce n'est pas lent. Ajoutez un sort i_tab , et cela donnera même le bon résultat. Cela fonctionnera de la même manière que la réponse de @ I.B.N., juste un peu plus gênant.


@ I.B.N. la solution est O (n) pour la partie boucle. Il a besoin d'une clé secondaire pour être O (log n). Cependant, cette solution est O (1) par défaut, pas besoin de définir une clé secondaire. C'est bien mieux.


READ TABLE i_tab est bien O (1), mais vous l'appelez dans un WHILE , ce qui en fait O (n). Elle est identique à la solution de @ I.B.N, mais pas aussi lisible.


@ András vous voyez Index utilisé dans les lignes "lire la table". C'est O (1). période.


c'est o (1) par exécutions . Vous en faites plus d'un, si tous les champs key sont égaux à x , vous faites n . Exactement comme I.B.N ...