Der FILTER-Ausdruck erstellt eine gefilterte Kopie einer internen Tabelle. Er ist die moderne, performante Alternative zu LOOP AT ... WHERE mit APPEND. Voraussetzung: Die Quelltabelle benötigt einen sortierten oder gehashten Schlüssel.
Syntax
1. Filtern mit WHERE-Bedingung
FILTER <typ>( <quelltabelle> [ USING KEY <schlüssel> ] WHERE <bedingung>)2. Filtern mit Filtertabelle (IN)
FILTER <typ>( <quelltabelle> [ USING KEY <schlüssel> ] IN <filtertabelle> WHERE <feld> = <filterfeld>)3. Filtern mit EXCEPT (NOT IN)
FILTER <typ>( <quelltabelle> [ EXCEPT [ IN <filtertabelle> ] ] WHERE <bedingung>)Voraussetzungen
Wichtig: FILTER erfordert einen sortierten oder gehashten Schlüssel auf den Filterfeldern:
" SORTED TABLE mit SchlüsselDATA: lt_data TYPE SORTED TABLE OF ty_data WITH UNIQUE KEY id.
" STANDARD TABLE mit sekundärem sortierten SchlüsselDATA: lt_data TYPE STANDARD TABLE OF ty_data WITH NON-UNIQUE SORTED KEY by_status COMPONENTS status.Beispiele
1. Grundlegendes Filtern mit WHERE
TYPES: BEGIN OF ty_order, order_id TYPE i, status TYPE string, amount TYPE p DECIMALS 2, END OF ty_order.
" Sortierte Tabelle erforderlichDATA: lt_orders TYPE SORTED TABLE OF ty_order WITH UNIQUE KEY order_id WITH NON-UNIQUE SORTED KEY by_status COMPONENTS status.
lt_orders = VALUE #( ( order_id = 1 status = 'OPEN' amount = '100.00' ) ( order_id = 2 status = 'COMPLETED' amount = '200.00' ) ( order_id = 3 status = 'OPEN' amount = '150.00' ) ( order_id = 4 status = 'CANCELLED' amount = '50.00' ) ( order_id = 5 status = 'OPEN' amount = '300.00' )).
" Nur offene Bestellungen filternDATA(lt_open_orders) = FILTER #( lt_orders USING KEY by_status WHERE status = 'OPEN').
" Ergebnis: order_id 1, 3, 5LOOP AT lt_open_orders INTO DATA(ls_order). WRITE: / ls_order-order_id, ls_order-amount.ENDLOOP.2. Vergleich: FILTER vs. LOOP AT WHERE
" KLASSISCH: Mit LOOP und APPENDDATA: lt_result TYPE TABLE OF ty_order.LOOP AT lt_orders INTO DATA(ls_ord) WHERE status = 'OPEN'. APPEND ls_ord TO lt_result.ENDLOOP.
" MODERN: Mit FILTER (performanter bei großen Tabellen)DATA(lt_result2) = FILTER #( lt_orders USING KEY by_status WHERE status = 'OPEN').3. Filtern mit Filtertabelle (IN)
TYPES: BEGIN OF ty_product, product_id TYPE i, category TYPE string, name TYPE string, END OF ty_product.
DATA: lt_products TYPE SORTED TABLE OF ty_product WITH UNIQUE KEY product_id WITH NON-UNIQUE SORTED KEY by_cat COMPONENTS category.
lt_products = VALUE #( ( product_id = 1 category = 'A' name = 'Produkt 1' ) ( product_id = 2 category = 'B' name = 'Produkt 2' ) ( product_id = 3 category = 'A' name = 'Produkt 3' ) ( product_id = 4 category = 'C' name = 'Produkt 4' ) ( product_id = 5 category = 'B' name = 'Produkt 5' )).
" Filtertabelle mit gewünschten KategorienTYPES: BEGIN OF ty_filter, category TYPE string, END OF ty_filter.
DATA: lt_filter TYPE SORTED TABLE OF ty_filter WITH UNIQUE KEY category.
lt_filter = VALUE #( ( category = 'A' ) ( category = 'B' )).
" Produkte filtern, deren Kategorie in lt_filter vorkommtDATA(lt_filtered) = FILTER #( lt_products USING KEY by_cat IN lt_filter WHERE category = category).
" Ergebnis: Produkte mit Kategorie A und B (product_id 1, 2, 3, 5)4. EXCEPT – Ausschließen statt Einschließen
" Produkte AUSSER Kategorie A und BDATA(lt_except) = FILTER #( lt_products USING KEY by_cat EXCEPT IN lt_filter WHERE category = category).
" Ergebnis: Nur Produkt 4 (Kategorie C)5. EXCEPT mit WHERE (ohne Filtertabelle)
TYPES: BEGIN OF ty_employee, emp_id TYPE i, department TYPE string, active TYPE abap_bool, END OF ty_employee.
DATA: lt_employees TYPE SORTED TABLE OF ty_employee WITH UNIQUE KEY emp_id WITH NON-UNIQUE SORTED KEY by_active COMPONENTS active.
lt_employees = VALUE #( ( emp_id = 1 department = 'IT' active = abap_true ) ( emp_id = 2 department = 'HR' active = abap_false ) ( emp_id = 3 department = 'IT' active = abap_true ) ( emp_id = 4 department = 'Sales' active = abap_false )).
" Alle NICHT aktiven MitarbeiterDATA(lt_inactive) = FILTER #( lt_employees USING KEY by_active EXCEPT WHERE active = abap_true).
" Ergebnis: emp_id 2, 46. Mehrere Bedingungen
TYPES: BEGIN OF ty_item, id TYPE i, type TYPE string, priority TYPE i, END OF ty_item.
DATA: lt_items TYPE SORTED TABLE OF ty_item WITH UNIQUE KEY id WITH NON-UNIQUE SORTED KEY by_type_prio COMPONENTS type priority.
lt_items = VALUE #( ( id = 1 type = 'A' priority = 1 ) ( id = 2 type = 'A' priority = 2 ) ( id = 3 type = 'B' priority = 1 ) ( id = 4 type = 'A' priority = 1 ) ( id = 5 type = 'C' priority = 3 )).
" Filtern nach Typ UND PrioritätDATA(lt_high_prio_a) = FILTER #( lt_items USING KEY by_type_prio WHERE type = 'A' AND priority = 1).
" Ergebnis: id 1, 47. FILTER mit Standard-Tabelle und Sekundärschlüssel
" Standard-Tabelle mit sekundärem SchlüsselDATA: lt_data TYPE STANDARD TABLE OF ty_order WITH NON-UNIQUE SORTED KEY k_status COMPONENTS status.
lt_data = VALUE #( ( order_id = 1 status = 'NEW' amount = 100 ) ( order_id = 2 status = 'DONE' amount = 200 ) ( order_id = 3 status = 'NEW' amount = 150 )).
" FILTER nutzt den sekundären SchlüsselDATA(lt_new) = FILTER #( lt_data USING KEY k_status WHERE status = 'NEW').8. FILTER in Methodenaufrufen
METHODS: process_orders IMPORTING it_orders TYPE ty_orders.
" Direkt gefilterte Daten übergebenprocess_orders( it_orders = FILTER #( lt_all_orders USING KEY by_status WHERE status = 'PENDING' )).9. FILTER mit Range-Tabelle
TYPES: BEGIN OF ty_sales, sales_id TYPE i, region TYPE string, revenue TYPE p DECIMALS 2, END OF ty_sales.
DATA: lt_sales TYPE SORTED TABLE OF ty_sales WITH UNIQUE KEY sales_id WITH NON-UNIQUE SORTED KEY by_region COMPONENTS region.
lt_sales = VALUE #( ( sales_id = 1 region = 'NORTH' revenue = 1000 ) ( sales_id = 2 region = 'SOUTH' revenue = 2000 ) ( sales_id = 3 region = 'EAST' revenue = 1500 ) ( sales_id = 4 region = 'NORTH' revenue = 1800 )).
" Filtertabelle mit RegionenTYPES: BEGIN OF ty_region_filter, region TYPE string, END OF ty_region_filter.
DATA: lt_regions TYPE SORTED TABLE OF ty_region_filter WITH UNIQUE KEY region.
lt_regions = VALUE #( ( region = 'NORTH' ) ( region = 'SOUTH' )).
DATA(lt_filtered_sales) = FILTER #( lt_sales USING KEY by_region IN lt_regions WHERE region = region).10. Kombination mit anderen Ausdrücken
" Mit VALUE und FOR kombinierenDATA(lt_processed) = VALUE ty_result_tab( FOR ls_item IN FILTER #( lt_items USING KEY by_type_prio WHERE type = 'A' ) ( id = ls_item-id description = |Item { ls_item-id } - Prio { ls_item-priority }| )).
" Mit REDUCE für AggregationDATA(lv_total) = REDUCE p DECIMALS 2( INIT sum = CONV p DECIMALS 2( 0 ) FOR ls_order IN FILTER #( lt_orders USING KEY by_status WHERE status = 'COMPLETED' ) NEXT sum = sum + ls_order-amount).11. Performance-Vergleich
" === INEFFIZIENT: LOOP ohne Index ===DATA: lt_result TYPE TABLE OF ty_order.LOOP AT lt_orders INTO ls_order WHERE status = 'OPEN'. APPEND ls_order TO lt_result.ENDLOOP." → Linearer Durchlauf O(n)
" === EFFIZIENT: FILTER mit Schlüssel ===DATA(lt_result2) = FILTER #( lt_orders USING KEY by_status WHERE status = 'OPEN')." → Nutzt Index für schnellen Zugriff O(log n) bis O(1)Wann FILTER verwenden?
| Situation | Empfehlung |
|---|---|
| Sortierte/Gehashte Tabelle vorhanden | FILTER #() |
| Filtern nach Schlüsselfeldern | FILTER #() |
| Standard-Tabelle ohne Schlüssel | LOOP AT … WHERE |
| Komplexe Bedingungen (nicht im Schlüssel) | LOOP AT … WHERE |
| Große Datenmengen mit Index | FILTER #() |
| Filtern mit IN-Tabelle | FILTER … IN |
FILTER vs. Alternativen
" 1. FILTER #() - Benötigt sortierten/gehashten SchlüsselDATA(lt_a) = FILTER #( lt_data USING KEY k WHERE status = 'X' ).
" 2. LOOP AT ... WHERE - Flexibler, aber potenziell langsamerLOOP AT lt_data INTO ls_data WHERE status = 'X'. APPEND ls_data TO lt_b.ENDLOOP.
" 3. FOR ... WHERE - Flexibel, inline nutzbarDATA(lt_c) = VALUE ty_tab( FOR ls IN lt_data WHERE ( status = 'X' ) ( ls )).
" 4. REDUCE mit COND - Für komplexe FilterlogikDATA(lt_d) = REDUCE ty_tab( INIT result = VALUE ty_tab( ) FOR ls IN lt_data NEXT result = COND #( WHEN ls-status = 'X' THEN VALUE #( BASE result ( ls ) ) ELSE result )).Wichtige Hinweise / Best Practice
FILTERerfordert einen sortierten oder gehashten Schlüssel auf den Filterfeldern.- Ohne passenden Schlüssel → Syntaxfehler.
USING KEYgibt an, welcher Schlüssel verwendet wird.FILTERist performanter alsLOOP AT WHEREbei großen Tabellen mit Index.INermöglicht Filtern gegen eine Filtertabelle (ähnlich SQL IN).EXCEPTinvertiert die Filterlogik (ausschließen statt einschließen).- Kombinieren Sie mit
VALUE,FORundREDUCE. - Bei Standard-Tabellen ohne Schlüssel nutzen Sie
LOOP AT ... WHERE. - Die Filtertabelle bei
INmuss ebenfalls sortiert oder gehasht sein. FILTERerstellt eine Kopie – die Originaltabelle bleibt unverändert.