Virtual Sorting ermöglicht die sortierte Verarbeitung interner Tabellen, ohne die physische Reihenfolge der Zeilen zu ändern. Mit der SORT ... BY-Syntax in Tabellenausdrücken und Iterationen kannst du Daten in einer bestimmten Reihenfolge durchlaufen, während die Originaltabelle unverändert bleibt.
Was ist Virtual Sorting?
Virtual Sorting ist ein Konzept, bei dem die Sortierreihenfolge temporär für eine Operation definiert wird, ohne die Tabelle selbst zu modifizieren. Das ist besonders nützlich, wenn:
- Mehrere Sortierreihenfolgen parallel benötigt werden
- Die Originaltabelle nicht verändert werden soll
- Performance bei großen Tabellen kritisch ist
| Aspekt | Physisches SORT | Virtual Sorting |
|---|---|---|
| Originaltabelle | Wird verändert | Bleibt unverändert |
| Reihenfolge | Dauerhaft | Temporär für Operation |
| Mehrere Sortierungen | Nacheinander | Parallel möglich |
| Speicher | In-Place | Zusätzlicher Index |
Verfügbarkeit
Virtual Sorting mit FOR ... IN ... USING KEY und dynamischen Keys ist seit ABAP 7.40 verfügbar. Die erweiterten Möglichkeiten mit sekundären Keys sind vollständig ABAP Cloud-kompatibel.
Praxisbeispiel: Verkaufsdaten analysieren
Ein typisches Szenario ist die Analyse von Verkaufsdaten, die in verschiedenen Sortierungen ausgewertet werden sollen:
CLASS zcl_virtual_sorting DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. INTERFACES if_oo_adt_classrun.
TYPES: BEGIN OF ty_s_sale, sale_id TYPE i, product TYPE string, region TYPE string, amount TYPE p DECIMALS 2, sale_date TYPE d, END OF ty_s_sale.
" Tabelle mit sekundären Keys für virtuelle Sortierung TYPES ty_t_sales TYPE SORTED TABLE OF ty_s_sale WITH UNIQUE KEY sale_id WITH NON-UNIQUE SORTED KEY by_amount COMPONENTS amount DESCENDING WITH NON-UNIQUE SORTED KEY by_region COMPONENTS region WITH NON-UNIQUE SORTED KEY by_date COMPONENTS sale_date DESCENDING.
ENDCLASS.
CLASS zcl_virtual_sorting IMPLEMENTATION.
METHOD if_oo_adt_classrun~main. DATA(lt_sales) = VALUE ty_t_sales( ( sale_id = 1 product = 'Laptop' region = 'Nord' amount = '1200.00' sale_date = '20260110' ) ( sale_id = 2 product = 'Monitor' region = 'Süd' amount = '450.00' sale_date = '20260115' ) ( sale_id = 3 product = 'Tastatur' region = 'Nord' amount = '89.00' sale_date = '20260112' ) ( sale_id = 4 product = 'Server' region = 'West' amount = '5500.00' sale_date = '20260108' ) ( sale_id = 5 product = 'Mouse' region = 'Süd' amount = '35.00' sale_date = '20260120' ) ).
out->write( '=== Originale Reihenfolge (nach sale_id) ===' ). LOOP AT lt_sales INTO DATA(ls_sale). out->write( |{ ls_sale-sale_id }: { ls_sale-product } - { ls_sale-amount }| ). ENDLOOP.
out->write( '' ). out->write( '=== Nach Umsatz (höchster zuerst) ===' ). LOOP AT lt_sales INTO ls_sale USING KEY by_amount. out->write( |{ ls_sale-product }: { ls_sale-amount } EUR| ). ENDLOOP.
out->write( '' ). out->write( '=== Nach Region ===' ). LOOP AT lt_sales INTO ls_sale USING KEY by_region. out->write( |{ ls_sale-region }: { ls_sale-product }| ). ENDLOOP.
out->write( '' ). out->write( '=== Nach Datum (neueste zuerst) ===' ). LOOP AT lt_sales INTO ls_sale USING KEY by_date. out->write( |{ ls_sale-sale_date DATE = USER }: { ls_sale-product }| ). ENDLOOP. ENDMETHOD.
ENDCLASS.Sekundäre Keys für Virtual Sorting
Der Schlüssel zu Virtual Sorting sind sekundäre Tabellenkeys. Sie definieren alternative Sortierreihenfolgen, die der ABAP-Kernel automatisch verwaltet.
Key-Typen
" Primärer Key (Identifikation)WITH UNIQUE KEY sale_id
" Sekundärer SORTED Key (automatisch sortiert gehalten)WITH NON-UNIQUE SORTED KEY by_amount COMPONENTS amount DESCENDING
" Sekundärer HASHED Key (für schnelle Lookups)WITH UNIQUE HASHED KEY by_product COMPONENTS productVergleich: Physisch vs. Virtuell
CLASS zcl_sort_comparison DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. INTERFACES if_oo_adt_classrun.
TYPES: BEGIN OF ty_s_item, item_id TYPE i, name TYPE string, value TYPE p DECIMALS 2, END OF ty_s_item.
TYPES ty_t_items TYPE SORTED TABLE OF ty_s_item WITH UNIQUE KEY item_id WITH NON-UNIQUE SORTED KEY by_value COMPONENTS value DESCENDING.
ENDCLASS.
CLASS zcl_sort_comparison IMPLEMENTATION.
METHOD if_oo_adt_classrun~main. DATA(lt_items) = VALUE ty_t_items( ( item_id = 1 name = 'A' value = '100.00' ) ( item_id = 2 name = 'B' value = '300.00' ) ( item_id = 3 name = 'C' value = '200.00' ) ).
" PHYSISCHE Sortierung - verändert die Tabelle DATA(lt_sorted_copy) = lt_items. SORT lt_sorted_copy BY value DESCENDING.
out->write( '=== Physisch sortierte Kopie ===' ). LOOP AT lt_sorted_copy INTO DATA(ls_sorted). out->write( |{ ls_sorted-name }: { ls_sorted-value }| ). ENDLOOP.
" VIRTUELLE Sortierung - Original bleibt unverändert out->write( '' ). out->write( '=== Virtuell sortiert (USING KEY) ===' ). LOOP AT lt_items INTO DATA(ls_virtual) USING KEY by_value. out->write( |{ ls_virtual-name }: { ls_virtual-value }| ). ENDLOOP.
" Original ist unverändert out->write( '' ). out->write( '=== Original (unverändert) ===' ). LOOP AT lt_items INTO DATA(ls_original). out->write( |{ ls_original-name }: { ls_original-value }| ). ENDLOOP. ENDMETHOD.
ENDCLASS.Virtual Sorting mit FOR-Ausdrücken
Virtual Sorting funktioniert auch in funktionalen Konstrukten wie FOR-Schleifen und REDUCE:
CLASS zcl_virtual_sort_for DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. INTERFACES if_oo_adt_classrun.
TYPES: BEGIN OF ty_s_order, order_id TYPE i, customer TYPE string, amount TYPE p DECIMALS 2, priority TYPE i, END OF ty_s_order.
TYPES ty_t_orders TYPE SORTED TABLE OF ty_s_order WITH UNIQUE KEY order_id WITH NON-UNIQUE SORTED KEY by_priority COMPONENTS priority WITH NON-UNIQUE SORTED KEY by_amount COMPONENTS amount DESCENDING.
TYPES: BEGIN OF ty_s_output, rank TYPE i, info TYPE string, END OF ty_s_output. TYPES ty_t_output TYPE STANDARD TABLE OF ty_s_output WITH EMPTY KEY.
ENDCLASS.
CLASS zcl_virtual_sort_for IMPLEMENTATION.
METHOD if_oo_adt_classrun~main. DATA(lt_orders) = VALUE ty_t_orders( ( order_id = 101 customer = 'Müller' amount = '500.00' priority = 2 ) ( order_id = 102 customer = 'Schmidt' amount = '1500.00' priority = 1 ) ( order_id = 103 customer = 'Weber' amount = '300.00' priority = 3 ) ( order_id = 104 customer = 'Fischer' amount = '2000.00' priority = 1 ) ).
" FOR mit USING KEY - Reihenfolge für Konstruktor bestimmen DATA(lt_by_priority) = VALUE ty_t_output( FOR ls_order IN lt_orders USING KEY by_priority INDEX INTO lv_idx ( rank = lv_idx info = |{ ls_order-customer } (Prio { ls_order-priority }): { ls_order-amount } EUR| ) ).
out->write( '=== Nach Priorität sortiert (VALUE FOR) ===' ). LOOP AT lt_by_priority INTO DATA(ls_output). out->write( |{ ls_output-rank }. { ls_output-info }| ). ENDLOOP.
" Top 2 nach Betrag mit REDUCE DATA(lv_top2_total) = REDUCE p DECIMALS 2( INIT sum = CONV p DECIMALS 2( 0 ) count = 0 FOR ls_ord IN lt_orders USING KEY by_amount WHILE count < 2 NEXT sum = sum + ls_ord-amount count = count + 1 ).
out->write( '' ). out->write( |Top 2 Bestellungen Summe: { lv_top2_total } EUR| ).
" Filter kombiniert mit virtueller Sortierung DATA(lt_high_priority) = VALUE ty_t_output( FOR ls_o IN lt_orders USING KEY by_amount WHERE ( priority <= 2 ) INDEX INTO lv_i ( rank = lv_i info = |{ ls_o-customer }: { ls_o-amount }| ) ).
out->write( '' ). out->write( '=== Hohe Priorität, nach Betrag ===' ). LOOP AT lt_high_priority INTO DATA(ls_hp). out->write( |{ ls_hp-rank }. { ls_hp-info }| ). ENDLOOP. ENDMETHOD.
ENDCLASS.Performance-Betrachtung
Virtual Sorting mit sekundären Keys bietet Performance-Vorteile, hat aber auch Kosten:
Wann sekundäre Keys verwenden
| Situation | Empfehlung |
|---|---|
| Häufig gleiche Sortierung | ✅ Sekundärer Key lohnt sich |
| Einmalige Sortierung | ❌ Physisches SORT effizienter |
| Mehrere parallele Sortierungen | ✅ Ideal für sekundäre Keys |
| Sehr große Tabellen (>100.000) | ⚠️ Speicherkosten abwägen |
| Häufige INSERT/DELETE | ⚠️ Key-Pflege kostet Performance |
Performance-Messung
CLASS zcl_virtual_sort_perf DEFINITION PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION. INTERFACES if_oo_adt_classrun.
TYPES: BEGIN OF ty_s_data, id TYPE i, value TYPE p DECIMALS 2, END OF ty_s_data.
" Mit sekundärem Key TYPES ty_t_with_key TYPE SORTED TABLE OF ty_s_data WITH UNIQUE KEY id WITH NON-UNIQUE SORTED KEY by_value COMPONENTS value.
" Ohne sekundären Key TYPES ty_t_no_key TYPE SORTED TABLE OF ty_s_data WITH UNIQUE KEY id.
ENDCLASS.
CLASS zcl_virtual_sort_perf IMPLEMENTATION.
METHOD if_oo_adt_classrun~main. " Testdaten generieren DATA lt_with_key TYPE ty_t_with_key. DATA lt_no_key TYPE ty_t_no_key.
DO 10000 TIMES. DATA(lv_value) = CONV p DECIMALS 2( sy-index MOD 1000 ). INSERT VALUE #( id = sy-index value = lv_value ) INTO TABLE lt_with_key. INSERT VALUE #( id = sy-index value = lv_value ) INTO TABLE lt_no_key. ENDDO.
" Variante 1: Virtual Sorting mit Key DATA(lv_start1) = cl_abap_context_info=>get_system_time( ). DATA(lv_sum1) = REDUCE p DECIMALS 2( INIT sum = CONV p DECIMALS 2( 0 ) FOR ls_data IN lt_with_key USING KEY by_value NEXT sum = sum + ls_data-value ). DATA(lv_end1) = cl_abap_context_info=>get_system_time( ).
" Variante 2: Physisches SORT + Iteration DATA(lt_copy) = CORRESPONDING ty_t_no_key( lt_no_key ). DATA(lv_start2) = cl_abap_context_info=>get_system_time( ). SORT lt_copy BY value. DATA(lv_sum2) = REDUCE p DECIMALS 2( INIT sum = CONV p DECIMALS 2( 0 ) FOR ls_data IN lt_copy NEXT sum = sum + ls_data-value ). DATA(lv_end2) = cl_abap_context_info=>get_system_time( ).
out->write( |Virtual Sorting: { lv_end1 - lv_start1 } ms| ). out->write( |Physisches SORT: { lv_end2 - lv_start2 } ms| ). out->write( |Summe identisch: { COND #( WHEN lv_sum1 = lv_sum2 THEN 'Ja' ELSE 'Nein' ) }| ). ENDMETHOD.
ENDCLASS.Best Practices
DO: Sekundäre Keys sinnvoll nutzen
" GUT: Key für häufig genutzte SortierungTYPES ty_t_products TYPE SORTED TABLE OF ty_s_product WITH UNIQUE KEY product_id WITH NON-UNIQUE SORTED KEY by_price COMPONENTS price DESCENDING.
" Iteration in gewünschter ReihenfolgeLOOP AT lt_products INTO DATA(ls_prod) USING KEY by_price. " Verarbeitung nach Preis absteigendENDLOOP.DON’T: Übermäßig viele Keys definieren
" SCHLECHT: Zu viele sekundäre Keys" Jeder Key belegt Speicher und kostet bei INSERT/DELETETYPES ty_t_overkill TYPE SORTED TABLE OF ty_s_data WITH UNIQUE KEY id WITH NON-UNIQUE SORTED KEY k1 COMPONENTS field1 WITH NON-UNIQUE SORTED KEY k2 COMPONENTS field2 WITH NON-UNIQUE SORTED KEY k3 COMPONENTS field3 WITH NON-UNIQUE SORTED KEY k4 COMPONENTS field4 WITH NON-UNIQUE SORTED KEY k5 COMPONENTS field5. " Zu viel!
" BESSER: Nur die wirklich benötigten KeysTYPES ty_t_balanced TYPE SORTED TABLE OF ty_s_data WITH UNIQUE KEY id WITH NON-UNIQUE SORTED KEY by_priority COMPONENTS priority.ABAP Cloud Kompatibilität
| Aspekt | Status |
|---|---|
| BTP ABAP Environment | ✅ Vollständig unterstützt |
| S/4HANA Cloud | ✅ Vollständig unterstützt |
| S/4HANA On-Premise | ✅ Ab 7.40 |
| Released API Status | ✅ Kernsprachfeature |
Virtual Sorting mit sekundären Keys ist ein Kernsprachfeature von ABAP und kann in allen ABAP Cloud-Umgebungen ohne Einschränkungen verwendet werden.
Zusammenfassung
Virtual Sorting ermöglicht elegante Lösungen für Mehrfach-Sortierungen:
- Sekundäre Keys definieren alternative Sortierreihenfolgen
- USING KEY aktiviert die virtuelle Sortierung in LOOP und FOR
- Original bleibt unverändert - keine Seiteneffekte
- Performance-Vorteil bei wiederholten Sortierungen
- Speicherkosten für sekundäre Keys beachten
- Kombinierbar mit REDUCE, VALUE, und anderen funktionalen Konstrukten
Besonders bei Reporting-Szenarien, wo Daten in verschiedenen Ansichten dargestellt werden müssen, ist Virtual Sorting eine elegante und performante Lösung.