I have a structure in ABAP :
id werks name1
My query is :
SELECT werks name1
INTO TABLE lt_store
FROM t001w
WHERE vlfkz EQ 'A'.
It is possible to add a field id that contains a incrementable value for example :
id werks name1
-----------------------
1 R0001 test
2 ERT3 test2 .....
and to do some SELECT like that
SELECT (value) werks name FROM...
My solution is to do a loop on lt_store and add value manually but I think it was optimize if we do that directly into the query.
What you want cannot be done with OpenSQL. Depending on the database you are running this on you might be able to put something together in Native SQL, but for this requirement I would not recommend that since there is a simple solution with the LOOP.
Open SQL doesn't support aggregate functions, but you can optimize a bit with a field symbol:
LOOP AT lt_store assignin <fs_store>.
<fs_store>-id = sy-tabix.
ENDLOOP.
You can use sy-tabix field while processing your results in loop.
for example,
LOOP AT lt_store INTO ls_store.
WRITE: /(1) sy-tabix, (5) ls_store-werks, (15)ls_store-name1.
ENDLOOP.
Related
I am still very inexperienced with SAP ABAP.
I have an internal table that I want to filter further and further based on whether data is present.
I have tried the following, but unfortunately I cannot apply a SELECT to an internal table.
How can I solve this problem?
Hope I have explained my problem clearly enough!
"Here I'm getting the hole database into my internal table
SELECT * FROM TABLE
INTO CORRESPONDING FIELDS OF TABLE #itab.
"This should be my first filter if iv_name is not initial
IF iv_name IS NOT INITIAL.
SELECT * FROM itab
WHERE NAME = #iv_name
INTO CORRESPONDING FIELDS OF TABLE #itab.
ENDIF.
"This should be my second filter if iv_age is not initial
IF iv_age IS NOT INITIAL.
SELECT * FROM itab
WHERE AGE = #iv_age
INTO CORRESPONDING FIELDS OF TABLE #itab.
ENDIF.
There are several ways in ABAP to achieve your goal.
You can use the DELETE keyword to filter the data in an internal table:
IF iv_name IS NOT INITIAL
DELETE itab WHERE name NE iv_name.
ENDIF.
Another possibility is to use the FILTER keyword, but the prerequisite is, that the internal table is TYPE SORTED or HASHED:
itab = FILTER #( itab WHERE name = iv_name ).
So my goal is to change a field in a table for those entries that the value is contained in some other table.
So for example.
If the name "John" from table_abc is contained in the table l_t_xyz then change the value to "ABC".
My approach to this:
SELECT * FROM table_xyz INTO TABLE #DATA(l_t_xyz).
Let's say one of the field of table_xyz is NAME.
And i have a second table, also with the field NAME where I want to change one of the fields
LOOP AT table_abc ASSIGNING FIELD-SYMBOL(<abc_line>) WHERE name in table_xyz-name.
<abc_line>-name = 'ABC'
ENDLOOP.
But this gives me an error that table_xyz is a table without a header line, therefore has no component called "NAME".
How do I solve this. Also I can't find any documentation on the keyword IN. Maybe I am using it wrong in this case.
So I have found another solution, which was inspired by Eray answer.
Basing on ranges
SELECT 'I' AS sign,
'EQ' AS option,
name as low
name as high
into table #DATA(range_table)
LOOP AT table_abc[] ASSIGNING FIELD-SYMBOL(<abc_line>) WHERE name in range_table.
<abc_line>-name = 'abc'
ENDLOOP.
You should define a range for name values which stored in table_xyz.
That's quick example:
TYPES lr_name_range_type TYPE RANGE OF name. "you should define appropriate data type
DATA : lr_name_range TYPE lr_name_range_type.
//define macro
DEFINE fill_range.
lr_name_range = VALUE #( BASE lr_name_range( sign = 'I' option = 'EQ' low = &1 ) ).
END-OF-DEFINITION.
//fill range according to table_xyz values
LOOP AT table_xyz ASSIGNING FIELD-SYMBOL(<fs_xyz>).
fill_range <fs_xyz>-name.
ENDLOOP.
//Now you can use IN keyword for your loop
LOOP AT table_abc ASSIGNING FIELD-SYMBOL(<abc_line>) WHERE name in lr_name_range.
<abc_line>-name = 'ABC'
ENDLOOP.
It's faster:
data lt_name type hashed table of table_xyz-name with unique default key.
SELECT * FROM table_xyz INTO TABLE #DATA(l_t_xyz).
lt_name = value #( for group fgv_name of <fs_xyz> in l_t_xyz
group by <fs_xyz>-name
( fgv_name )
).
LOOP AT table_abc ASSIGNING FIELD-SYMBOL(<fs_line>).
if line_exists( lt_name[ table_line = <fs_line>-name ] )
<fs_line>-name = 'ABC'.
endif.
ENDLOOP.
In the old ABAP syntax I have to loop over the source table, and inside of the loop append value to the table.
For example:
DATA:
it_source_table type table of mara,
et_result_table type table of matnr.
loop at it_source_table into data(ls_source_table).
append ls_source_table-matnr to et_result_table.
endloop.
Is there with a new ABAP syntax (750, 752) ("move-corresponding", "value#") a way to achieve the same in less sentences?
You can use the VALUE operator with the FOR ... IN addition:
et_result_table = VALUE #( FOR material IN it_source_table ( material-matnr ) ).
I have two standard tables, VBAP and MAKT.
I want elements of MAKT-MAKTX, where MAKT-MATNR = VBAP - MATNR.
SELECT MATNR FROM VBAP INTO IT_VBAP.
SELECT MATNR MAKTX FROM MAKT INTO IT_MAKT FOR ALL ENTRIES WHERE MATNR = IT_VBAP.
Does this code choose values in it_makt where only those matnr fields are equal?
What exactly does for all entries does.
Thank you.
select field_1 field_2 field_n from table into internal_table for all
entries in another_internal_table where some_field_in_table = another_internal_table-same_field_in_another_internal_table.
You use for all entries when you want to fill an internal table according to values in another internal table.
You can try using the following
select matnr from vbap into it_vbap.
select maktx from makt into it_makt for all entries in it_vbap where matnr = it_vbap-matnr.
For all entries is the the exact thing, You might think, as You read it. It is like this:
"For all entries in" allows You to use a subset of an internal table as where condition in a select statement by the possibility to provide the fields of this internal table as where condition-parameters in the select statement.
So, internally it is also only a loop, You can use the sql-monitor transaction, and mostly will see, that for all entries really behaves like a select inside a loop if I remember correctly. It is quite helpful, and usually used relatively often.
If the subset-table, which is used as parameter-table is empty, then You perform a full table select (full table scan), if You only use the tables fields as where parameters. So always pay attention to the select which fills Your where-table or check its contents with if lines( the_table ) > 0. Nevertheless take a look at vwegert's link, it describes the pros and cons of for all entries. Do You need more info ?
I am running into the following problem, I am passing an array of string into Oracle SQL, and I would like to retrieve all the data where its id is in the list ...
here's what i've tried ...
OPEN O_default_values FOR
SELECT ID AS "Header",
VALUE AS "DisplayValue",
VALUE_DESC AS "DisplayText"
FROM TBL_VALUES
WHERE ID IN I_id;
I_id is an array described as follows - TYPE gl_id IS TABLE OF VARCHAR2(15) INDEX BY PLS_INTEGER;
I've been getting the "expression is of wrong type" error.
The I_id array can sometimes be as large as 600 records.
My question is, is there a way to do what i just describe, or do i need to create some sort of cursor and loop through the array?
What has been tried - creating the SQL string dynamically and then con-cat the values to the end of the SQL string and then execute it. This will work for small amount of data and the size of the string is static, which will caused some other errors (like index out of range).
have a look at this link: http://asktom.oracle.com/pls/asktom/f?p=100:11:620533477655526::::P11_QUESTION_ID:139812348065
effectively what you want is a variable in-list with bind variables.
do note this:
"the" is deprecated. no need for it
today.
TABLE is it's replacement
select * from TABLE( function );
since you already have the type, all you need to do is something similar to below:
OPEN O_default_values FOR
SELECT ID AS "Header",
VALUE AS "DisplayValue",
VALUE_DESC AS "DisplayText"
FROM TBL_VALUES
WHERE ID IN (select column_value form table(I_id));