1
votes

Sélectionnez la ligne du tableau où la valeur de la colonne a la "priorité la plus élevée"

J'ai une table de base de données avec les colonnes DOC1, DOC2 et CLIENT. J'essaie de sélectionner une ligne par CLIENT, dont la colonne DOC1 a la priorité la plus élevée en fonction de l'ordre suivant, de la priorité la plus élevée à la plus basse: ITCI> ITPP> ITPS> ITPT.

Voici un exemple.

Select single doc1  doc2 (W_doc1, W_doc2)
        FROM /BI0/Pdoctax
        WHERE  client eq <RESULT_FIELDS>-client. 

OUTPUT^

La table de destination doit avoir CLIENT a une clé unique et je dois ajouter les deux colonnes DOC1 et DOC2, en prenant la ligne qui a DOC1 avec la priorité la plus élevée.

CLIENT DOC2 DOC1
101   GG319 ITCI
102   YB311 ITPP

J'ai écrit un single select in end routine mais il y avait une erreur de syntaxe:

DOC1  DOC2  CLIENT
ITCI  GG319  101
ITPS  YB311  102  
ITPT  GG319  101
ITPP  YB311  102


1 commentaires

DOC2 n'a pas de règles maintenant, pouvez-vous nous dire ce dont vous avez besoin?


4 Réponses :


0
votes

Si je comprends bien, vous voulez que la sélection ne génère qu'une une ligne par CLIENT, en choisissant la ligne dans le tableau d'origine en fonction de ces priorités DOC1.

Une telle sélection n'est pas possible.

Au sommet de ma tête, ce sont les possibilités que je propose, mais il y en a probablement d'autres. En fonction de votre situation, vous devrez déterminer lequel correspond le mieux à vos besoins.

  1. Vous pouvez tout sélectionner, BOUCLER dessus et créer votre format avec des conditions IF, etc.

  2. Si vous n'avez vraiment que ces 4 possibilités DOC1, vous pouvez tout sélectionner, trier la table interne par CLIENT et DOC1, puis supprimer les doublons adjacents en comparant uniquement CLIENT. Cela fonctionnerait car "ITCI> ITPP> ITPS> ITPT" est dans l'ordre alphabétique.

  3. Encore une fois, si vous n'avez que ces 4 possibilités DOC1, vous pouvez les sélectionner l'une après l'autre, en vérifiant s'il y a encore des CLIENTS manquants.


1 commentaires

salut Legix, «Si je comprends bien, vous voulez que la sélection ne produise qu'une seule ligne par CLIENT, en choisissant la ligne de la table d'origine en fonction de ces priorités DOC1.» «Oui, j'essaie de le faire. pouvez-vous m'aider avec du code j'ai 6 types de doc1



1
votes

Comme votre ordre de priorité du plus élevé au plus bas ressemble entièrement à l'ordre alphabétique, vous n'avez besoin de rien de plus que d'utiliser GROUP BY avec une agrégation MIN:

SELECT client, MIN( doc2 ) AS doc2, MIN( doc1 ) AS doc1
INTO TABLE @DATA(itab)
FROM /BI0/Pdoctax
GROUP BY client.

Dans les cas plus complexes où le classement n'est pas aussi primitif, vous pouvez utiliser la clause CASE .


2 commentaires

Je pense que l'OP ne veut pas de MIN (DOC2), il veut la valeur DOC2 qui correspond à la ligne qui contient la valeur minimale de DOC1 pour le client donné


Je ne sais pas, mais la sortie ressemble exactement à ce que vous souhaitez. Peut-être que sur des chaînes de priorité plus complexes, cela échouera, mais pour le cas ci-dessus, cela fonctionne



0
votes

Étant donné que vos valeurs de priorité doc1 sont en fait de six, cela devrait fonctionner.

  DATA lt_priorities TYPE STANDARD TABLE OF /bi0/pdoctax-doc1.
  lt_priorities = VALUE #( ( 'ITCI' ) ( 'ITPS' ) ( 'ITPT' ) ( 'ITPP' ) ( 'P500' ) ( 'P600' ) ).

  SELECT b~client,
         doc1,
         doc2
    FROM /bi0/pdoctax AS b
   WHERE b~client = @<result_fields>-client
   ORDER BY doc1 ASCENDING
    INTO TABLE @DATA(lt_doctax).

  DATA ls_doctax_filtered LIKE LINE OF lt_doctax.

  LOOP AT lt_priorities ASSIGNING FIELD-SYMBOL(<fs_priority>).
    READ TABLE lt_doctax ASSIGNING FIELD-SYMBOL(<fs_doctax>)
      WITH KEY doc1 = <fs_priority> BINARY SEARCH.
    IF sy-subrc = 0.
      ls_doctax_filtered = <fs_doctax>.
*     --->
      EXIT.
    ENDIF.
  ENDLOOP.

Je suppose que vous recherchez une réponse qui fait cela dans une seule instruction SELECT, sinon vous pouvez boucler:

SELECT b~client,
       coalesce( p1~doc1, p2~doc1, p3~doc1, p4~doc1, p5~doc1, p6~doc1 ),
       coalesce( p1~doc2, p2~doc2, p3~doc2, p4~doc2, p5~doc2, p6~doc2 )
  FROM /bi0/pdoctax AS b
                 LEFT OUTER JOIN /bi0/pdoctax AS p1
                 ON  p1~client = b~client
                 AND p1~doc1   = 'ITCI'
                 LEFT OUTER JOIN /bi0/pdoctax AS p2
                 ON  p2~client = b~client
                 AND p2~doc1   = 'ITPS'
                 LEFT OUTER JOIN /bi0/pdoctax AS p3
                 ON  p3~client = b~client
                 AND p3~doc1   = 'ITPT'
                 LEFT OUTER JOIN /bi0/pdoctax AS p4
                 ON  p4~client = b~client
                 AND p4~doc1   = 'ITPT'
                 LEFT OUTER JOIN /bi0/pdoctax AS p5
                 ON  p4~client = b~client
                 AND p4~doc1   = 'P5'
                 LEFT OUTER JOIN /bi0/pdoctax AS p6
                 ON  p4~client = b~client
                 AND p4~doc1   = 'P6'
  WHERE b~client = @<result_fields>-client
   INTO @DATA(ls_doctax).


0 commentaires

0
votes

Voici une solution "simple" avec ABAP 7.52.

J'ai utilisé un autre exemple pour les tests afin que tout le monde puisse jouer avec: j'ai utilisé la table de démonstration SFLIGHT qui est fournie avec tout Installation ABAP. Exécutez le programme SAPBC_DATA_GENERATOR pour générer des données si la table est vide.

Comme déjà mentionné par d'autres personnes, il est supposé que votre priorité est basée sur l'ordre alphabétique, donc la fonction d'agrégation MIN peut être utilisé.

Le code ci-dessous obtient les lignes de SFLIGHT qui correspond à chaque valeur distincte de la colonne CARRID (équivalent à CLIENT dans votre question ) et sa valeur minimale dans la colonne PAYMENTSUM (DOC1) (les deux dans la sous-requête EXISTS ):

SELECT carrid, fldate AS doc2, paymentsum AS doc1
FROM sflight AS a
WHERE EXISTS (
        SELECT carrid
        FROM sflight
        WHERE carrid = a~carrid
        GROUP BY carrid
        HAVING MIN( paymentsum ) = a~paymentsum )
INTO TABLE @DATA(itab).

Contenu de la table de base de données SFLIGHT (via SE16 / résultat attendu mis en évidence): entrez la description de l'image ici

Contenu de la table interne itab (via debug / comme prévu): entrez la description de l'image ici

Remarque sur le code SQL ABAP:

  • Toute sélection sur un résultat d'agrégation ne peut être effectuée qu'après HAVING, pas après WHERE (règle SQL classique).
  • Si plusieurs lignes de SFLIGHT ont les mêmes valeurs pour CARRID et PAYMENTSUM, alors l'une de ces lignes est sélectionnée au hasard (règle SQL classique).
  • Il fonctionne dans ABAP 7.52 mais peut ne pas fonctionner dans les anciennes versions.
  • Pour les futurs visiteurs ayant une demande plus complexe, cette solution peut rapidement devenir impossible à adapter.
  • Il peut y avoir des solutions plus simples en "SQL natif" (utilisation directe de la base de données SQL), comme l'utilisation de SELECT ... FROM (SELECT ...) (non autorisé jusqu'à ABAP SQL 7.53)


0 commentaires