From 93a2788207f268ca28c4d99e4de29ef8f9aa39a8 Mon Sep 17 00:00:00 2001 From: Daniel Reger <16720986+danrega@users.noreply.github.com> Date: Wed, 11 Jan 2023 13:56:38 +0100 Subject: [PATCH] Update FILTER operator --- 01_Internal_Tables.md | 77 +++++++++--- 05_Constructor_Expressions.md | 60 ++++++++-- src/zcl_demo_abap_constructor_expr.clas.abap | 117 ++++++++++++++----- src/zcl_demo_abap_internal_tables.clas.abap | 111 +++++++++++++----- 4 files changed, 285 insertions(+), 80 deletions(-) diff --git a/01_Internal_Tables.md b/01_Internal_Tables.md index 48340d1..d8a6366 100644 --- a/01_Internal_Tables.md +++ b/01_Internal_Tables.md @@ -776,24 +776,71 @@ ENDIF. ``` Creating an internal table by copying data from another internal table -filtering out lines that do not match the `WHERE` condition. -Using the [`FILTER` -operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_filter.htm) -to extract data from internal tables ... +filtering out lines that do not match the `WHERE` condition using the [`FILTER` +operator](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_filter.htm). -... by condition. -``` abap -DATA(filter1) = FILTER #( itab WHERE comp1 < i ). -``` +- The + `FILTER` operator constructs an internal table according to a specified type (which can be an explicitly specified, non-generic table type or the # character as a symbol for the [operand type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_type_glosry.htm) before the first parenthesis). +- The lines for the new internal table are taken from an + existing internal table based on conditions specified in a `WHERE` clause. Note that the table type of the existing internal table must be convertible to the specified target type. +- The conditions can either be based on single values or a [filter + table](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expr_filter_table.htm). +- Additions: -... by condition with the addition `EXCEPT` that excludes data according to a condition. -``` abap -DATA(filter2) = FILTER #( itab EXCEPT WHERE comp1 < i ). -``` +|Addition |Details | +|---|---| +|`USING KEY` | Specifies the [table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_key_glosry.htm "Glossary Entry") with which the `WHERE` condition is evaluated: either a [sorted key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensorted_key_glosry.htm "Glossary Entry") or a [hash key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhash_key_glosry.htm "Glossary Entry"). If the internal table has neither of them, a [secondary table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensecondary_table_key_glosry.htm "Glossary Entry") must be available for the internal table which must then be specified after `USING KEY`. | +| `EXCEPT` | The specification of `EXCEPT` means that those lines of the existing table are used that do not meet the condition specified in the `WHERE` clause. Hence, if `EXCEPT` is not specified, the lines of the existing table are used that meet the condition. | -... by using a filter table. -``` abap -DATA(filter3) = FILTER #( itab IN filter_tab WHERE comp1 < i. +Examples: +```abap +"FILTER an conditions based on single values +"Assumption the component num is of type i. +DATA itab1 TYPE SORTED TABLE OF struc WITH NON-UNIQUE KEY num. +DATA itab2 TYPE STANDARD TABLE OF struc WITH NON-UNIQUE SORTED KEY sec_key COMPONENTS num. +DATA itab3 TYPE HASHED TABLE OF struc WITH UNIQUE KEY num. + +"The lines meeting the condition are respected. +"Note: The source table must have at least one sorted or hashed key. +"Here, the primary key is used +DATA(f1) = FILTER #( itab1 WHERE num >= 3 ). + +"USING KEY primary_key explicitly specified; same as above +DATA(f2) = FILTER #( itab1 USING KEY primary_key WHERE num >= 3 ). + +"EXCEPT addition +DATA(f3) = FILTER #( itab1 EXCEPT WHERE num >= 3 ). +DATA(f4) = FILTER #( itab1 EXCEPT USING KEY primary_key WHERE num >= 3 ). + +"Secondary table key specified after USING KEY +DATA(f5) = FILTER #( itab2 USING KEY sec_key WHERE num >= 4 ). +DATA(f6) = FILTER #( itab2 EXCEPT USING KEY sec_key WHERE num >= 3 ). + +"Note: In case of a hash key, exactly one comparison expression for each key component is allowed; +"only = as comparison operator possible. +DATA(f7) = FILTER #( itab3 WHERE num = 3 ). + +"Using a filter table +"In the WHERE condition, the columns of source and filter table are compared. Those lines in the source table +"are used for which at least one line in the filter table meets the condition. EXCEPT and USING KEY are also possible. + +DATA filter_tab1 TYPE SORTED TABLE OF i + WITH NON-UNIQUE KEY table_line. + +DATA filter_tab2 TYPE STANDARD TABLE OF i + WITH EMPTY KEY + WITH UNIQUE SORTED KEY line COMPONENTS table_line. + +DATA(f8) = FILTER #( itab1 IN filter_tab1 WHERE num = table_line ). + +"EXCEPT addition +DATA(f9) = FILTER #( itab1 EXCEPT IN filter_tab1 WHERE num = table_line ). + +"USING KEY is specified for the filter table +DATA(f10) = FILTER #( itab2 IN filter_tab2 USING KEY line WHERE num = table_line ). + +"USING KEY is specified for the source table, including EXCEPT +DATA(f11) = FILTER #( itab2 USING KEY sec_key EXCEPT IN filter_tab2 WHERE num = table_line ). ``` *Excursion:* Collecting values diff --git a/05_Constructor_Expressions.md b/05_Constructor_Expressions.md index fadee3c..d10a790 100644 --- a/05_Constructor_Expressions.md +++ b/05_Constructor_Expressions.md @@ -704,30 +704,68 @@ DATA(b) = SWITCH #( a ## `FILTER` - The - [`FILTER`](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expression_filter.htm) - operator constructs an internal table line by line based on an - existing table and conditions specified in a `WHERE` clause. + `FILTER` operator constructs an internal table according to a specified type (which can be an explicitly specified, non-generic table type or the # character as a symbol for the [operand type](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenoperand_type_glosry.htm) before the first parenthesis). +- The lines for the new internal table are taken from an + existing internal table based on conditions specified in a `WHERE` clause. Note that the table type of the existing internal table must be convertible to the specified target type. - The conditions can either be based on single values or a [filter table](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenconstructor_expr_filter_table.htm). - Additions: |Addition |Details | |---|---| -|`USING KEY` | Specifies the [table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_key_glosry.htm "Glossary Entry") with which the `WHERE` condition is evaluated, i. e. a [sorted key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensorted_key_glosry.htm "Glossary Entry") or a [hash key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhash_key_glosry.htm "Glossary Entry"). If the internal table has neither of them, a [secondary table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensecondary_table_key_glosry.htm "Glossary Entry") must be available and specified. | +|`USING KEY` | Specifies the [table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abentable_key_glosry.htm "Glossary Entry") with which the `WHERE` condition is evaluated: either a [sorted key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensorted_key_glosry.htm "Glossary Entry") or a [hash key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abenhash_key_glosry.htm "Glossary Entry"). If the internal table has neither of them, a [secondary table key](https://help.sap.com/doc/abapdocu_cp_index_htm/CLOUD/en-US/index.htm?file=abensecondary_table_key_glosry.htm "Glossary Entry") must be available for the internal table which must then be specified after `USING KEY`. | | `EXCEPT` | The specification of `EXCEPT` means that those lines of the existing table are used that do not meet the condition specified in the `WHERE` clause. Hence, if `EXCEPT` is not specified, the lines of the existing table are used that meet the condition. | Examples: -``` abap -DATA(f1) = FILTER #( tab WHERE comp > 5 ). +```abap +"FILTER an conditions based on single values +"Assumption the component num is of type i. +DATA itab1 TYPE SORTED TABLE OF struc WITH NON-UNIQUE KEY num. +DATA itab2 TYPE STANDARD TABLE OF struc WITH NON-UNIQUE SORTED KEY sec_key COMPONENTS num. +DATA itab3 TYPE HASHED TABLE OF struc WITH UNIQUE KEY num. -DATA(f2) = FILTER #( tab EXCEPT WHERE comp < 3 ). +"The lines meeting the condition are respected. +"Note: The source table must have at least one sorted or hashed key. +"Here, the primary key is used +DATA(f1) = FILTER #( itab1 WHERE num >= 3 ). -DATA(f3) = FILTER #( tab USING KEY x WHERE comp = 4 ). +"USING KEY primary_key explicitly specified; same as above +DATA(f2) = FILTER #( itab1 USING KEY primary_key WHERE num >= 3 ). -"Filtering based on another table -DATA(f3) = FILTER #( tab IN filter_tab -                     WHERE comp = 3 ). +"EXCEPT addition +DATA(f3) = FILTER #( itab1 EXCEPT WHERE num >= 3 ). +DATA(f4) = FILTER #( itab1 EXCEPT USING KEY primary_key WHERE num >= 3 ). + +"Secondary table key specified after USING KEY +DATA(f5) = FILTER #( itab2 USING KEY sec_key WHERE num >= 4 ). +DATA(f6) = FILTER #( itab2 EXCEPT USING KEY sec_key WHERE num >= 3 ). + +"Note: In case of a hash key, exactly one comparison expression for each key component is allowed; +"only = as comparison operator possible. +DATA(f7) = FILTER #( itab3 WHERE num = 3 ). + +"Using a filter table +"In the WHERE condition, the columns of source and filter table are compared. Those lines in the source table +"are used for which at least one line in the filter table meets the condition. EXCEPT and USING KEY are also possible. + +DATA filter_tab1 TYPE SORTED TABLE OF i + WITH NON-UNIQUE KEY table_line. + +DATA filter_tab2 TYPE STANDARD TABLE OF i + WITH EMPTY KEY + WITH UNIQUE SORTED KEY line COMPONENTS table_line. + +DATA(f8) = FILTER #( itab1 IN filter_tab1 WHERE num = table_line ). + +"EXCEPT addition +DATA(f9) = FILTER #( itab1 EXCEPT IN filter_tab1 WHERE num = table_line ). + +"USING KEY is specified for the filter table +DATA(f10) = FILTER #( itab2 IN filter_tab2 USING KEY line WHERE num = table_line ). + +"USING KEY is specified for the source table, including EXCEPT +DATA(f11) = FILTER #( itab2 USING KEY sec_key EXCEPT IN filter_tab2 WHERE num = table_line ). ```

(back to top)

diff --git a/src/zcl_demo_abap_constructor_expr.clas.abap b/src/zcl_demo_abap_constructor_expr.clas.abap index 167abf6..7c9b1f1 100644 --- a/src/zcl_demo_abap_constructor_expr.clas.abap +++ b/src/zcl_demo_abap_constructor_expr.clas.abap @@ -19,7 +19,7 @@ * numbers (e. g. 1) ..., 2) ..., 3) ...) for the individual example * sections. Plus, the variable name is displayed in most cases. Hence, * to easier and faster find the relevant output in the console, just -* search in the console for the number/variable name (STRG+F in the +* search in the console for the number/variable name (CTRL+F in the * console) or use the debugger. * * ----------------------------- NOTE ----------------------------------- @@ -948,41 +948,102 @@ CLASS ZCL_DEMO_ABAP_CONSTRUCTOR_EXPR IMPLEMENTATION. output->next_section( `10. FILTER` ). - "The examples demonstrate the use of the FILTER operator. - "1) Method to fill internal table with demo values. The tables are - "displayed to show the original values of the internal table that is to - "be filtered. - "2) Filters an internal table based on a condition specified after - "WHERE. A new internal table is created that is declared inline. - "3) A new table is created based on filtering a table. Here, the - "addition EXCEPT is used that excludes data according to a condition - "specified after WHERE. - "4) The filtering is based on entries in a filter table. + "This section covers multiple examples demonstrating the syntactical variety + "of the FILTER operator. - "1) Method to fill demo internal table with values to work with. - "The table is displayed showing the values. - fill_struc_and_tab( ). + TYPES: BEGIN OF fi_str, + a TYPE i, + b TYPE c LENGTH 3, + c TYPE c LENGTH 3, + END OF fi_str. - "2) Filtering an internal table based on a condition. - DATA(filter1) = FILTER #( tab4 WHERE comp3 > 5 ). + "basic form, condition created with single values + "itab must have at least one sorted key or one hash key used for access. + "This variant of the filter operator is not possible for an internal table itab without a sorted key or hash key. + DATA fi_tab1 TYPE SORTED TABLE OF fi_str WITH NON-UNIQUE KEY a. + DATA fi_tab2 TYPE STANDARD TABLE OF fi_str WITH NON-UNIQUE SORTED KEY sec_key COMPONENTS a. + DATA fi_tab3 TYPE HASHED TABLE OF fi_str WITH UNIQUE KEY a. - "3) Filtering an internal table using EXCEPT addition - DATA(filter2) = FILTER #( tab4 EXCEPT WHERE comp3 < 3 ). + "Filling internal tables + fi_tab1 = VALUE #( ( a = 1 b = 'aaa' c = 'abc' ) + ( a = 2 b = 'bbb' c = 'def' ) + ( a = 3 b = 'ccc' c = 'hij' ) + ( a = 4 b = 'ddd' c = 'klm' ) + ( a = 5 b = 'eee' c = 'nop' ) ). - "4) Filtering an internal table using a filter table. - "Creating and filling a filter table. - DATA extract_tab TYPE SORTED TABLE OF i + fi_tab2 = fi_tab1. + fi_tab3 = fi_tab1. + + "The lines meeting the condition are respected. + "Note: The source table must have at least one sorted or hashed key. + "Here, the primary key is used + DATA(f1) = FILTER #( fi_tab1 WHERE a >= 3 ). + + output->display( input = f1 name = `f1` ). + + "USING KEY primary_key explicitly specified; same as above + DATA(f2) = FILTER #( fi_tab1 USING KEY primary_key WHERE a >= 3 ). + + output->display( input = f2 name = `f2` ). + + "EXCEPT addition + DATA(f3) = FILTER #( fi_tab1 EXCEPT WHERE a >= 3 ). + + output->display( input = f3 name = `f3` ). + + DATA(f4) = FILTER #( fi_tab1 EXCEPT USING KEY primary_key WHERE a >= 3 ). + + output->display( input = f4 name = `f4` ). + + "Secondary table key specified after USING KEY + DATA(f5) = FILTER #( fi_tab2 USING KEY sec_key WHERE a >= 4 ). + + output->display( input = f5 name = `f5` ). + + DATA(f6) = FILTER #( fi_tab2 EXCEPT USING KEY sec_key WHERE a >= 3 ). + + output->display( input = f6 name = `f6` ). + + "Note: In case of a hash key, exactly one comparison expression for each key + "component is allowed; only = as comparison operator possible. + DATA(f7) = FILTER #( fi_tab3 WHERE a = 3 ). + + output->display( input = f7 name = `f7` ). + + "Using a filter table + "In the WHERE condition, the columns of source and filter table are compared. + "Those lines in the source table are used for which at least one line in the + "filter table meets the condition. EXCEPT and USING KEY are also possible. + + "Declaring and filling filter tables + DATA filter_tab1 TYPE SORTED TABLE OF i WITH NON-UNIQUE KEY table_line. - extract_tab = VALUE #( ( 3 ) ( 5 ) ). + DATA filter_tab2 TYPE STANDARD TABLE OF i + WITH EMPTY KEY + WITH UNIQUE SORTED KEY line COMPONENTS table_line. - DATA(filter3) = FILTER #( tab4 IN extract_tab - WHERE comp3 = table_line ). + filter_tab1 = VALUE #( ( 3 ) ( 5 ) ). + filter_tab2 = filter_tab1. - output->display( input = tab4 name = `tab4` ). - output->display( input = filter1 name = `filter1` ). - output->display( input = filter2 name = `filter2` ). - output->display( input = filter3 name = `filter3` ). + DATA(f8) = FILTER #( fi_tab1 IN filter_tab1 WHERE a = table_line ). + + output->display( input = f8 name = `f8` ). + + "EXCEPT addition + DATA(f9) = FILTER #( fi_tab1 EXCEPT IN filter_tab1 WHERE a = table_line ). + + output->display( input = f9 name = `f9` ). + + "USING KEY is specified for the filter table + DATA(f10) = FILTER #( fi_tab2 IN filter_tab2 USING KEY line WHERE a = table_line ). + + output->display( input = f10 name = `f10` ). + + "USING KEY is specified for the source table, including EXCEPT + DATA(f11) = FILTER #( fi_tab2 USING KEY sec_key EXCEPT IN filter_tab2 WHERE a = table_line ). + + output->display( input = f11 name = `f11` ). output->next_section( `11. Iteration Expressions with FOR` ). diff --git a/src/zcl_demo_abap_internal_tables.clas.abap b/src/zcl_demo_abap_internal_tables.clas.abap index 872fcf3..8ac2994 100644 --- a/src/zcl_demo_abap_internal_tables.clas.abap +++ b/src/zcl_demo_abap_internal_tables.clas.abap @@ -19,7 +19,7 @@ * numbers (e. g. 1) ..., 2) ..., 3) ...) for the individual example * sections. Plus, the variable name is displayed in most cases. Hence, * to easier and faster find the relevant output in the console, just -* search in the console for the number/variable name (STRG+F in the +* search in the console for the number/variable name (CTRL+F in the * console) or use the debugger. * * ----------------------------- NOTE ----------------------------------- @@ -620,43 +620,102 @@ CLASS ZCL_DEMO_ABAP_INTERNAL_TABLES IMPLEMENTATION. output->next_section( `22) FILTER: Filtering internal table by condition` ). - TYPES t_itab2filter TYPE SORTED TABLE OF zdemo_abap_tab1 - WITH NON-UNIQUE KEY key_field. + "This section covers multiple examples demonstrating the syntactical variety + "of the FILTER operator. - DATA itab2filter TYPE t_itab2filter. + TYPES: BEGIN OF fi_str, + a TYPE i, + b TYPE c LENGTH 3, + c TYPE c LENGTH 3, + END OF fi_str. - "Retrieving data for the example in an internal table - SELECT key_field, char1, char2, num1, num2 - FROM zdemo_abap_tab1 - INTO CORRESPONDING FIELDS OF TABLE @itab2filter UP TO 4 ROWS. + "basic form, condition created with single values + "itab must have at least one sorted key or one hash key used for access. + "This variant of the filter operator is not possible for an internal table itab without a sorted key or hash key. + DATA fi_tab1 TYPE SORTED TABLE OF fi_str WITH NON-UNIQUE KEY a. + DATA fi_tab2 TYPE STANDARD TABLE OF fi_str WITH NON-UNIQUE SORTED KEY sec_key COMPONENTS a. + DATA fi_tab3 TYPE HASHED TABLE OF fi_str WITH UNIQUE KEY a. - "New internal table is constructed by filtering out lines from - "another one. - DATA(filtered1) = FILTER #( itab2filter WHERE key_field < 400 ). + "Filling internal tables + fi_tab1 = VALUE #( ( a = 1 b = 'aaa' c = 'abc' ) + ( a = 2 b = 'bbb' c = 'def' ) + ( a = 3 b = 'ccc' c = 'hij' ) + ( a = 4 b = 'ddd' c = 'klm' ) + ( a = 5 b = 'eee' c = 'nop' ) ). - output->display( input = filtered1 name = `filtered1` ). + fi_tab2 = fi_tab1. + fi_tab3 = fi_tab1. - output->next_section( `23) FILTER: Filtering internal table by ` && - `condition with the addition EXCEPT that excludes data ` && - `according to condition` ). + "The lines meeting the condition are respected. + "Note: The source table must have at least one sorted or hashed key. + "Here, the primary key is used + DATA(f1) = FILTER #( fi_tab1 WHERE a >= 3 ). - DATA(filtered2) = FILTER #( itab2filter - EXCEPT WHERE key_field < 300 ). + output->display( input = f1 name = `f1` ). - output->display( input = filtered2 name = `filtered2` ). + "USING KEY primary_key explicitly specified; same as above + DATA(f2) = FILTER #( fi_tab1 USING KEY primary_key WHERE a >= 3 ). - output->next_section( `24) FILTER: Filtering internal table by ` && - `using another filter table` ). + output->display( input = f2 name = `f2` ). - "Filling the filter table. - DATA(extract) = VALUE t_itab2filter( ( key_field = 100 ) - ( key_field = 300 ) ). + "EXCEPT addition + DATA(f3) = FILTER #( fi_tab1 EXCEPT WHERE a >= 3 ). - DATA(filtered3) = FILTER #( itab2filter IN extract - WHERE key_field = key_field ). + output->display( input = f3 name = `f3` ). - output->display( input = filtered3 name = `filtered3` ). + DATA(f4) = FILTER #( fi_tab1 EXCEPT USING KEY primary_key WHERE a >= 3 ). + output->display( input = f4 name = `f4` ). + + "Secondary table key specified after USING KEY + DATA(f5) = FILTER #( fi_tab2 USING KEY sec_key WHERE a >= 4 ). + + output->display( input = f5 name = `f5` ). + + DATA(f6) = FILTER #( fi_tab2 EXCEPT USING KEY sec_key WHERE a >= 3 ). + + output->display( input = f6 name = `f6` ). + + "Note: In case of a hash key, exactly one comparison expression for each key + "component is allowed; only = as comparison operator possible. + DATA(f7) = FILTER #( fi_tab3 WHERE a = 3 ). + + output->display( input = f7 name = `f7` ). + + "Using a filter table + "In the WHERE condition, the columns of source and filter table are compared. + "Those lines in the source table are used for which at least one line in the + "filter table meets the condition. EXCEPT and USING KEY are also possible. + + "Declaring and filling filter tables + DATA filter_tab1 TYPE SORTED TABLE OF i + WITH NON-UNIQUE KEY table_line. + + DATA filter_tab2 TYPE STANDARD TABLE OF i + WITH EMPTY KEY + WITH UNIQUE SORTED KEY line COMPONENTS table_line. + + filter_tab1 = VALUE #( ( 3 ) ( 5 ) ). + filter_tab2 = filter_tab1. + + DATA(f8) = FILTER #( fi_tab1 IN filter_tab1 WHERE a = table_line ). + + output->display( input = f8 name = `f8` ). + + "EXCEPT addition + DATA(f9) = FILTER #( fi_tab1 EXCEPT IN filter_tab1 WHERE a = table_line ). + + output->display( input = f9 name = `f9` ). + + "USING KEY is specified for the filter table + DATA(f10) = FILTER #( fi_tab2 IN filter_tab2 USING KEY line WHERE a = table_line ). + + output->display( input = f10 name = `f10` ). + + "USING KEY is specified for the source table, including EXCEPT + DATA(f11) = FILTER #( fi_tab2 USING KEY sec_key EXCEPT IN filter_tab2 WHERE a = table_line ). + + output->display( input = f11 name = `f11` ). output->next_section( `25) Inserting data into an internal table ` && `using a COLLECT statement` ).