[ABAP] Gruppierung von LOOP-Elementen (LOOP, GROUP BY), Group-Member

Beispiel 1 (einfach)

TYPES: BEGIN OF ty_person,
         person_id TYPE char3,
         name      TYPE char10,
         city      TYPE char3,
       END OF ty_person.

TYPES: ty_it_persons TYPE STANDARD TABLE OF ty_person WITH DEFAULT KEY.

DATA(it_persons) = VALUE ty_it_persons( ( person_id = 'P01' name = 'Horst' city = 'HAM' )
                                        ( person_id = 'P02' name = 'Udo'   city = 'BER' )
                                        ( person_id = 'P03' name = 'Inge'  city = 'HAM' )
                                        ( person_id = 'P04' name = 'Edit'  city = 'BER' )
                                        ( person_id = 'P05' name = 'Agnes' city = 'HAM' )
                                        ( person_id = 'P06' name = 'Ede'   city = 'LEI' ) ).

* Gruppierung nach City
* Aufsteigend sortiert
* mit Members (Unterelemente)
LOOP AT it_persons ASSIGNING FIELD-SYMBOL(<c>) GROUP BY <c>-city ASCENDING.

  LOOP AT GROUP <c> ASSIGNING FIELD-SYMBOL(<p>).
    WRITE: / '  ', <p>-person_id, <p>-name, <p>-city.
  ENDLOOP.

* neue interne Tabelle aus der Gruppe generieren
  DATA(it_cp) = VALUE ty_it_persons( FOR <cp> IN GROUP <c> ( <cp> ) ).

  ...

  ULINE.
ENDLOOP.

Beispiel 2 (WHERE, ASCENDING, ASSIGNING FIELD-SYMBOL)

TYPES: BEGIN OF ty_person,
         person_id TYPE char3,
         name      TYPE char10,
         city      TYPE char3,
         street    TYPE char20,
       END OF ty_person.

TYPES: ty_it_persons TYPE STANDARD TABLE OF ty_person WITH DEFAULT KEY.

* Testdaten mit Städten und Personen
DATA(it_persons) = VALUE ty_it_persons( ( person_id = 'P01' name = 'Horst' city = 'HAM' street = 'Allee' )
                                        ( person_id = 'P02' name = 'Udo'   city = 'BER' street = 'Kudamm' )
                                        ( person_id = 'P03' name = 'Inge'  city = 'HAM' street = 'Allee' )
                                        ( person_id = 'P04' name = 'Edit'  city = 'BER' street = 'Müllerstr.' )
                                        ( person_id = 'P05' name = 'Agnes' city = 'HAM' street = 'Hauptstraße' )
                                        ( person_id = 'P06' name = 'Ede'   city = 'LEI' street = 'Zentralplatz' )
                                        ( person_id = 'P07' name = 'Ida'   city = 'LEI' street = 'Zentralplatz' )
                                        ( person_id = 'P08' name = 'Ulf'   city = 'LEI' street = 'Poststraße' )
                                        ( person_id = 'P09' name = 'Ingo'  city = 'BER' street = 'Uferweg' )
                                        ( person_id = 'P10' name = 'Heinz' city = 'LEI' street = 'Postplatz' )
                                        ( person_id = 'P11' name = 'Heini' city = 'HAM' street = 'Postweg' )
                                      ).

* Suchkriterien für die Liste
DATA(rg_city) = VALUE rseloption( ( sign = 'I' option = 'EQ' low = 'HAM' high = '' )
                                  ( sign = 'I' option = 'EQ' low = 'LEI' high = '' ) ).

* Personenliste anhand der Suchkriterien für city durchloopen
LOOP AT it_persons ASSIGNING FIELD-SYMBOL(<g>) WHERE city IN rg_city
  GROUP BY ( city  = <g>-city       " Gruppierung nach feld 'city'
             size  = GROUP SIZE     " Anz. Elemente der akt. Gruppe in <gp>
             index = GROUP INDEX )  " Index der Gruppe <gp>
  ASCENDING AS TEXT                 " Gruppen aufsteigend sortieren
  ASSIGNING FIELD-SYMBOL(<gp>).     " Zugriff auf die Gruppe über <gp>

  WRITE: / |       City: { <gp>-city  }|.
  WRITE: / |GROUP INDEX: { <gp>-index }|.
  WRITE: / | GROUP SIZE: { <gp>-size }|.
  WRITE: / |   sy-tabix: { sy-tabix }|.

* Unterelemente der Gruppe durchloopen
  LOOP AT GROUP <gp> ASSIGNING FIELD-SYMBOL(<pi>).
    WRITE: / |     sy-tabix: { sy-tabix }|.
    WRITE: / |         data: { <pi>-city } { <pi>-person_id } { <pi>-name } { <pi>-street } |.
  ENDLOOP.

  ULINE.

ENDLOOP.

Beispiel 3 (Hierarchie)

TYPES: BEGIN OF ty_person,
         person_id TYPE char3,
         name      TYPE char10,
         city      TYPE char3,
         street    TYPE char20,
       END OF ty_person.

TYPES: ty_it_persons TYPE STANDARD TABLE OF ty_person WITH DEFAULT KEY.

* Testdaten mit Städten und Personen
DATA(it_persons) = VALUE ty_it_persons( ( person_id = 'P01' name = 'Horst' city = 'HAM' street = 'Allee' )
                                        ( person_id = 'P02' name = 'Udo'   city = 'BER' street = 'Kudamm' )
                                        ( person_id = 'P03' name = 'Inge'  city = 'HAM' street = 'Allee' )
                                        ( person_id = 'P04' name = 'Edit'  city = 'BER' street = 'Müllerstr.' )
                                        ( person_id = 'P05' name = 'Agnes' city = 'HAM' street = 'Hauptstraße' )
                                        ( person_id = 'P06' name = 'Ede'   city = 'LEI' street = 'Zentralplatz' )
                                        ( person_id = 'P07' name = 'Ida'   city = 'LEI' street = 'Zentralplatz' )
                                        ( person_id = 'P08' name = 'Ulf'   city = 'LEI' street = 'Poststraße' )
                                        ( person_id = 'P09' name = 'Ingo'  city = 'BER' street = 'Uferweg' )
                                        ( person_id = 'P10' name = 'Heinz' city = 'LEI' street = 'Postplatz' )
                                        ( person_id = 'P11' name = 'Heini' city = 'HAM' street = 'Postweg' )
                                      ).

* Gruppierung nach City
* Aufsteigend sortiert
* mit Members (Unterelemente)
LOOP AT it_persons ASSIGNING FIELD-SYMBOL(<c>) GROUP BY <c>-city ASCENDING.
* Stadt ausgeben
  WRITE: / <c>-city.

* Gruppierung nach City->Straße
* Aufsteigend sortiert
* mit Members (Unterelemente)
  LOOP AT GROUP <c> ASSIGNING FIELD-SYMBOL(<s>) GROUP BY <s>-street ASCENDING.
    WRITE: / '  ', <s>-street.

    LOOP AT GROUP <s> ASSIGNING FIELD-SYMBOL(<p>).
      WRITE: / '    ', <p>-person_id, <p>-name.
    ENDLOOP.
  ENDLOOP.

  ULINE.
ENDLOOP.

Beispiel 4 (REFERENCE INTO mit und ohne MEMBERS)

TYPES: BEGIN OF ty_person,
         person_id TYPE char3,
         name      TYPE char10,
         city      TYPE char3,
       END OF ty_person.

* Sortierte Tabelle
TYPES: ty_it_persons TYPE SORTED TABLE OF ty_person WITH UNIQUE KEY person_id.

DATA(it_persons) = VALUE ty_it_persons( ( person_id = 'P01' name = 'Horst' city = 'HAM' )
                                        ( person_id = 'P02' name = 'Udo'   city = 'BER' )
                                        ( person_id = 'P03' name = 'Inge'  city = 'HAM' )
                                        ( person_id = 'P04' name = 'Edit'  city = 'BER' )
                                        ( person_id = 'P05' name = 'Agnes' city = 'HAM' )
                                        ( person_id = 'P06' name = 'Ede'   city = 'LEI' ) ).

* Gruppierung nach City
* Aufsteigend sortiert
* WITHOUT MEMBERS -> bessere Performance, aber kein Zugriff auf Unterelemente
LOOP AT it_persons ASSIGNING FIELD-SYMBOL(<c>)
  GROUP BY ( city  = <c>-city
             size  = GROUP SIZE
             index = GROUP INDEX )
  ASCENDING
  WITHOUT MEMBERS
  REFERENCE INTO DATA(o_city).

  WRITE: / |City: { o_city->city }, Size: { o_city->size }, Index: { o_city->index }|.
ENDLOOP.

ULINE.

* Gruppierung nach City
* Aufsteigend sortiert
* mit Members (Unterelemente)
LOOP AT it_persons ASSIGNING FIELD-SYMBOL(<c2>)
  GROUP BY ( city  = <c2>-city
             size  = GROUP SIZE
             index = GROUP INDEX )
  ASCENDING
  REFERENCE INTO DATA(o_city2).

  WRITE: / |City: { o_city2->city }, Size: { o_city2->size }, Index: { o_city2->index }|.

  LOOP AT GROUP o_city2 ASSIGNING FIELD-SYMBOL(<p>).
    WRITE: / '  ', <p>-person_id, <p>-name, <p>-city.
  ENDLOOP.
ENDLOOP.

Weiterführende Infos: Link und Link

[ABAP] MESH – Beziehungen zw. internen Tabellen abbilden (JOIN)

* https://answers.sap.com/questions/64735/what-are-meshes-really-good-for.html
* https://l3consulting.de/meshes-in-abap/
* http://zevolving.com/2015/05/abap-740-meshes-a-new-complex-type-of-structures/
* http://zevolving.com/2015/05/abap-740-mesh-path-forward-and-inverse-association/

* Demoprogramme:
*   DEMO_MESH_DELETE_NUMBERS
*   DEMO_MESH_DELETE_TABLE_NUMBERS
*   DEMO_MESH_EXPRESSIONS_FLIGHTS
*   DEMO_MESH_EXPRESSIONS_NUMBERS
*   DEMO_MESH_FORWARD_ASSOC
*   DEMO_MESH_FOR_FLIGHTS
*   DEMO_MESH_INSERT_BUILD_TABLE
*   DEMO_MESH_INSERT_NUMBERS
*   DEMO_MESH_INVERSE_ASSOC
*   DEMO_MESH_LOOP_AT_FLIGHTS
*   DEMO_MESH_LOOP_AT_NUMBERS
*   DEMO_MESH_MODIFY_NUMBERS
*   DEMO_MESH_MODIFY_TABLE_NUMBERS
*   DEMO_MESH_PACK
*   DEMO_MESH_REFLEXIVE_ASSOC_LOOP
*   DEMO_MESH_REFLEXIVE_ASSOC_SNGL
*   DEMO_MESH_REFLEXIVE_ASSOC_TREE
*   DEMO_MESH_SET_ASSOC_NUMBERS

* Orte
TYPES: BEGIN OF ty_orte,
         key_ort TYPE i,
         ort     TYPE string,
       END OF ty_orte.

* Personen
TYPES: BEGIN OF ty_personen,
         key_ort TYPE i,
         name    TYPE string,
         alter   TYPE i,
       END OF ty_personen.

TYPES: ty_it_orte TYPE SORTED TABLE OF ty_orte WITH UNIQUE KEY key_ort.
TYPES: ty_it_personen TYPE SORTED TABLE OF ty_personen WITH NON-UNIQUE KEY key_ort.

* MESH mit Assoziation
TYPES: BEGIN OF MESH ty_mesh,
         orte     TYPE ty_it_orte ASSOCIATION orte_to_personen TO personen ON key_ort = key_ort,
         personen TYPE ty_it_personen,
       END OF MESH ty_mesh.

DATA: it_mesh TYPE ty_mesh.

INITIALIZATION.
* Daten einpflegen
  it_mesh-orte = VALUE #( ( key_ort = 1 ort = 'FRA' )
                          ( key_ort = 2 ort = 'BER' )
                          ( key_ort = 3 ort = 'DRS' )
                          ( key_ort = 4 ort = 'MUN' )
                          ( key_ort = 5 ort = 'DUS' ) ).

  it_mesh-personen = VALUE #( ( key_ort = 1 name = 'Udo'      alter = 35 )
                              ( key_ort = 4 name = 'Horst'    alter = 60 )
                              ( key_ort = 3 name = 'Inge'     alter = 70 )
                              ( key_ort = 1 name = 'Elfriede' alter = 85 )
                              ( key_ort = 5 name = 'Florian'  alter = 16 ) ).

START-OF-SELECTION.

  WRITE: / 'Orte:'.
  LOOP AT it_mesh-orte ASSIGNING FIELD-SYMBOL(<o>).
    WRITE: / <o>-key_ort, <o>-ort.
  ENDLOOP.

  ULINE.

  WRITE: / 'Personen:'.
  LOOP AT it_mesh-personen ASSIGNING FIELD-SYMBOL(<p>).
    WRITE: / <p>-key_ort, <p>-name, <p>-alter.
  ENDLOOP.

  ULINE.

  TRY.
* Forward Association
      WRITE: / 'Forward Association Ort->Person ( key = 1 )'.
      DATA(lv_p) = it_mesh-orte\orte_to_personen[ it_mesh-orte[ key_ort = 1 ] ].
      WRITE: / lv_p-key_ort, lv_p-name, lv_p-alter.
    CATCH cx_root.
  ENDTRY.

  TRY.
* Inverse Assocition
      WRITE: / 'Inverse Assocition Ort->Personen->Ort( key_ort = 3 )'.
      DATA(lv_o) = it_mesh-personen\^orte_to_personen~orte[ it_mesh-personen[ key_ort = 3 ] ] .
      WRITE: / lv_o-key_ort, lv_o-ort.
    CATCH cx_root.
  ENDTRY.