Allowing duplicate in FOR ALL ENTRIES statement
Hi folks,
I am using a select query using FOR ALL ENTRIES statement. I could observe one entry is missing from the table data.When i checked that in the data base table, there are two duplicate records among which one entry is missed in the output data from the query.Is duplicates are restricted if we use FOR ALL ENTRIES statement ? Is there any key word like 'ALLOWING DUPLICATES' for this ? if not what is the solution for this.Could any body help me regarding this.
Thanks,
Shyam.
Edited by: Matt on Jul 9, 2009 1:27 PM
Hi Shyam,
In For all entries you should give unique records only.
sort your base table with key which you are passing in for all entries clause.
delete all duplicate entries.
Hope this will help .
Regards,
Vijay
Similar Messages
-
Select FOR ALL ENTRIES statement cannot get duplicates entries
Hi all,
t_yxapy_fields consist of
inty field
0001 kostl
0002 perid
0008 ansal
0008 preas
0008 trfst
The following is the code for me to transfer the contents of t_yxapy_fields into t_pa_fields.
SELECT dbtab
FROM t777d
INTO TABLE t_pa_fields
FOR ALL ENTRIES IN t_yxapy_fields
WHERE infty = t_yxapy_fields-infty.
And t_pa_fields just ended up with
field infty
pa0001
pa0002
pa0008
Question:The first table have 3 similar infotype 0008 but the result table only have one pa0008. I need to filled up acordingly as what table 1 have. I need another 2 pa0008 in my 2nd table. What is wrng with my Select for all entries statement here?
Edited by: Siong Chao on Mar 27, 2010 10:35 AMThis has nothing to do with duplicates in t777d.
Correct, I failed to recognize that table t777d has only infty as key as pointed out by Aby. Thus in your particular case my comment was misleading. In general though FOR ALL ENTRIES removes all duplicate rows from your result set.
If you want the other 2 values just loop t_yxapy_fields this table and read t_pa_fields and if record found add the other values to t_pa_fields table. --> will trigger performance tuning issue
I'm pretty sure if you'd code this, you won't run into any performance issues, so follow Aby's recipe. To be more concrete, here's what I'd do: Define a mapping table t777d_tab, which holds the translation from infty to dbtab:
types:
begin of T_T777D_VIEW,
INFTY type T777D-INFTY,
DBTAB type T777D-DBTAB,
end of T_T777D_VIEW.
data:
T777D_TAB type hashed table of T_T777D_VIEW with unique key INFTY.
Fill table t_pa_fields, typed using t_t777d_tab from above, from table t777d. Then loop over your table t_yxapy_fields (I'd use [LOOP AT ... ASSIGNING|http://help.sap.com/abapdocu_70/en/ABAPLOOP_AT_ITAB_RESULT.htm] instead of LOOP AT ... INTO) and for each entry get the corresponding DBTAB value from t777d_tab (again use the [READ TABLE ... ASSIGNING|http://help.sap.com/abapdocu_70/en/ABAPREAD_TABLE_OUTDESC.htm] variant) and build your result table t_pa_fields.
Anyhow, I suspect that even with less optimal coding (e.g. using just standard table for lookup of DBTAB values) you'd not see much of an performance impact, because it seems that your internal tables are most likely rather small...
Cheers, harald -
Coupling INNER JOIN with FOR ALL ENTRIES statement
Hi All,
I am coupling INNER JOIN with FOR ALL ENTRIES statement .....
Would you please highlight its implications ?? Is it a best practise ?
Is it advicable to use MULTIPLE INNER JOINs with a FOR ALL ENTRIES ???
SORT itab BY matnr.
IF NOT itab[] IS INITIAL.
SELECT epmatnr epebeln ep~ebelp
epwerks epmenge ep~netpr
ekps_psp_pnr ebbelnr eb~menge
INTO TABLE iekpo
FROM ekpo AS ep
INNER JOIN ekkn AS ek
ON ekebeln = epebeln
AND ekebelp = epebelp
INNER JOIN ekbe AS eb
ON ebebeln = epebeln
AND ebebelp = epebelp
AND eb~bwart = '101'
FOR ALL ENTRIES IN itab
WHERE ep~matnr = itab-matnr.
IF sy-subrc EQ 0.
SORT iekpo BY matnr werks.
LOOP AT itab ASSIGNING <itab>.
READ TABLE iekpo WITH KEY matnr = <itab>-matnr
werks = <itab>-werks
BINARY SEARCH.
IF sy-subrc EQ 0.
MOVE iekpo-matnr TO itab1-matnr.
MOVE iekpo-ebeln TO itab1-ebeln.
MOVE iekpo-ebelp TO itab1-ebelp.
MOVE iekpo-netpr TO itab1-poprice.
MOVE iekpo-werks TO itab1-werks.
MOVE iekpo-menge TO itab1-menge1.
MOVE iekpo-menge1 TO itab1-menge2.
MOVE iekpo-belnr TO itab1-belnr.
MOVE iekpo-ps_psp_pnr TO itab1-pspel.
MOVE <itab>-pspel TO itab1-tpspel.
MOVE <itab>-sobkz TO itab1-sobkz.
MOVE <itab>-fo_qty TO itab1-fo_qty.
MOVE <itab>-schgt TO itab1-schgt.
MOVE <itab>-postp TO itab1-postp.
MOVE <itab>-beskz TO itab1-beskz.
pend_qty = iekpo-menge1 - iekpo-menge2.
MOVE pend_qty TO itab1-pending.
APPEND itab1.
pend_qty = 0.
ENDIF.
ENDLOOP.
ENDIF.
ENDIF.
ENDIF.
Regards
Jaman
Edited by: ABAP Techie on Sep 15, 2008 12:39 PM
Edited by: ABAP Techie on Sep 15, 2008 12:41 PMbest practise ... don't know ... it is allowed and o.k.
If possible you should of coourse to have no FOR ALL ENTRIES at all !
Joins, there is no general rule, check indexes etc.
The first SORT, I don't that it help for anything, use it together with the delete adjacent duplicates if you expect duplicates in the driver table.
o.k., it can help, if there is a loop afterwards and an append inside, because the new table itab1 is then sorted.
Siegfried -
Regarding 'Select .... for all entries' statement
Hi experts,
Can anyone suggest me that whether we can use two internal tables in 'Select .... for all entries' statement?Hi,
You can use ranges instead of second for all entries.
Eg:
Say for example i need to write selec statement using fields from two int tables in where conidition namely itab1, itab2.
RANGES: r_vbeln FOR wa_tab1-vbeln.
LOOP AT itab1 INTO wa_tab1.
r_vbeln-sign = 'I'.
r_vbeln-option = 'EQ'.
r_vbeln-low = wa_tab1-vbeln.
APPEND r_vbeln.
ENDLOOP.
SELECT * FROM vbap INTO TABLE itab3
FOR ALL ENTRIES IN itab2
WHERE vbeln IN r_vbeln "range contains all vbeln from the table itab1
AND matwa = itab2-matwa.
Hope this helps you.
Regards,
Manoj Kumar P -
Problem with FOR ALL ENTRIES statement
Hi all
please find the problem in the select statement.
SELECT vbbe~vbeln
vbap~vstel
marc~dispo
vbbe~matnr
vbbe~kunnr
vbbe~werks
vbbe~mbdat
vbbe~omeng
INTO TABLE l_t_dvbeln
FROM vbbe
INNER JOIN vbak
ON
vbbe~vbeln = vbak~vbeln
inner join vbap
on
vbbe~vbeln = vbap~vbeln and
vbbe~matnr = vbap~matnr
inner join marc
on
vbbe~matnr = marc~matnr and
vbbe~werks = marc~werks
FOR ALL entries IN g_t_stock
WHERE vbbe~matnr = g_t_stock-matnr
AND vbbe~werks = g_t_stock-werks
AND vbak~vkorg = g_t_stock-vkorg
AND vbak~vtweg = g_t_stock-vtweg
AND vbbe~kunnr = g_t_stock-kunnr
AND vbbe~mbdat IN r_mbdat.
g_t_stock is having only one record i.e.,
g_t_stock-vstel = 'DF01'.
g_t_stock-dispo = 'DEI'.
g_t_stock-matnr = '00100833'.
g_t_stock-maktx = 'SAC (300X400)'.
g_t_stock-kunnr = '0000600431'.
g_t_stock-werks = 'PF71'.
g_t_stock-labst = '7727'.
g_t_stock-vkorg = 'SF71'.
g_t_stock-vtweg = 'IC'.
and r_mbdat has the date range as
r_mbdat-sign = I
r_mbdat-option = BT
r_mbdat-low = 15.05.2008
r_mbdat-high = 08.06.2008
In vbak vbap & marc tables i have only one record as per the above selection criteria.
in VBBE table i have 7 records which satisfies the above criteria. But the select staement retrieves only 5 records.
if we remove for all entries and hardcode the values in the select statement then it retrieves all 7 records.
can anybody help me.
what is the reason it is showing only 5 records.Hi all
actually it has to retrieve the following records
VBELN MATNR KUNNR WERKS MBDAT LABST
30001417 00100833 600431 PF71 15.05.2008 20.000
30001417 00100833 600431 PF71 15.05.2008 20.000
30001417 00100833 600431 PF71 22.05.2008 5.000
30001417 00100833 600431 PF71 22.05.2008 7.000
30001417 00100833 600431 PF71 27.05.2008 10.000
30001417 00100833 600431 PF71 27.05.2008 10.000
30001417 00100833 600431 PF71 29.05.2008 10.000
But it is retrieving only 5 records as below
VBELN MATNR KUNNR WERKS MBDAT LABST
30001417 00100833 600431 PF71 15.05.2008 20.000
30001417 00100833 600431 PF71 22.05.2008 5.000
30001417 00100833 600431 PF71 22.05.2008 7.000
30001417 00100833 600431 PF71 27.05.2008 10.000
30001417 00100833 600431 PF71 29.05.2008 10.000
Please give the reason -
Select for all entries statement
Hi
can some one send me a for allentries staterment for the following :
Tables : cvers, cvers_ref.
common field component.
very urgent.
points will be given....Hi!
DATA: gt_cvers LIKE STANDARD TABLE OF cvers,
gs_cvers LIKE LINE OF gt_cvers.
DATA: gt_cvers_ref LIKE STANDARD TABLE OF cvers_ref,
gs_cvers_ref LIKE LINE OF gt_cvers_ref.
SELECT-OPTIONS: s_comp FROM cvers-component.
SELECT * FROM cvers INTO TABLE gt_cvers
WHERE compnent IN s_comp.
IF sy-subrc = 0.
SELECT * FROM cvers_ref INTO TABLE gt_cvers_ref
FOR ALL ENTRIES IN gt_cvers
WHERE component = gt_cvers-component AND langu = sy-langu.
ENDIF.
Regards
Tamá -
Regarding SELECT FOR ALL ENTRIES AND DELETE ADJACENT DUPLICATES
Hi,
i got few doubts.....
1) Is it necessary to DELETE ADJACENT DUPLICATES when we perform a SELECT FOR ALL ENTRIES ? because for all entries itself eliminates the duplicate entries?
2) Wat Sy-subrc returns after a SELECT FOR ALL ENTRIES statement?
I found some code where these are used
SORT ITAB[] BY NEWKO[].
DELETE ADJACENT DUPLICATES FORM ITAB[].
SELECT buknr
kunnr
FORM KNB1
into table ITAB_KNB1
FOR ALL ENTRIES IN ITAB
where kunnr eq itab-newko.
Regards.
Maehsh.Hi Mahesh,
To be more specific, first you should delete "adjacent duplicates" using the sorting key ( here : NEWKO ), if Itab contains other fields.
SORT ITAB[] BY NEWKO[].
DELETE ADJACENT DUPLICATES FORM ITAB COMPARING NEWKO.
You can delete or not the duplicates, but, you must know that if you don't delete them in the Itab, you will retrieve them in the ITAB_KNB1.
Concerning the return code, it works like for the "SELECT" ( 0 = entries found / 4 = no entrie found )
=> One more thing, it's better check :
Check not ITab[] is initial
because, if the Itab is empty, you'll retrieve all the record of KNB1 !
Hope this helps,
Erwan.
Message was edited by:
Erwan LE BRUN -
Facin problems in the 'Select... for all entries'
I am facing problem with this piece of code, please share ur thoughts on it. I have specified the inputs.
I am extracting the open items from the BSIS table for specified 3 account number.
Inputs to the prg:
field No. of values
r_bukrs 1
r_hkont 2
r_blart 6
r_budat date range of 1 yr
r_bldat nil
v_tosdef contain 1 account number
" In each FI document posted, one line will have the 'v_tosdef' account number and one account from the 'r_hkont' values."
So will this query efficient.
SELECT bukrs
hkont
gjahr
belnr
budat
bldat
xblnr
blart
shkzg
dmbtr
FROM bsis
INTO TABLE i_bsis
WHERE bukrs IN r_bukrs " Company code
AND hkont = v_tosdef " Account number
AND budat IN r_budat " Posting date
AND bldat IN r_bldat " Document date
AND blart IN r_blart. " Document type
IF sy-subrc <> 0.
MESSAGE i003.
STOP.
ENDIF.
*@ Collecting the BELNR & GJAHR From the extracted records
li_bsis[] = i_bsis[].
SORT li_bsis BY bukrs gjahr belnr.
DELETE ADJACENT
DUPLICATES FROM li_bsis
COMPARING bukrs gjahr belnr.
IF NOT li_bsis[] IS INITIAL.
SELECT bukrs
hkont
gjahr
belnr
budat
bldat
xblnr
blart
shkzg
dmbtr
FROM bsis
APPENDING TABLE i_bsis
FOR ALL ENTRIES IN li_bsis
WHERE bukrs = li_bsis-bukrs " Company code
AND hkont IN r_hkont " Account number
AND gjahr = li_bsis-gjahr " Fiscal year
AND belnr = li_bsis-belnr. " Document num
BSIS table size around 86GB
primary index size aroung 33GB
and the index quality is 54%
the CBO shows less cost, but the actual runs takes too much disk read's / bgets..
Message was edited by:
SandyHi Sandy,
You indicated the size of the tables and index, what is the total number of records in your BSIS?
In your range tables, make sure they are postive formed.
Ex. r_bukrs : I EQ '1001', and not I NE '1000'.
You should consider coding your statements to check for input for bldat, code it with r_bldat and then another set without. It should be better performance to not have empty where conditions. So two routines, Selects with bldat and without.
Don't know if you have a Basis person to help analyze the performance, but you should look at the indexes in BSIS. You may have several indexes that contain some of your input fields but they may be spread across several indexes or there may be none. But say you have 5 indexes and it happens that just one of your parameters are in each of those indexes. Well, it can only use one index so while you think you are providing alot of parameters to help performance only one field is being used to access the index. What you need to do then is to find an index that has the most fields in your where clause and see if you can add to that, so long it's not an SAP index. If it's a z index consider adding additional fields to it, or consider creating a new index.
You can at least analyze the first Select in your DEV client. Run a trace, ST05 and then execute your code. It will show you which index it has used if any.
Also, look at the query values it is passing to the database. You said you get 6 M records on the first Select. This just seem like a lot of records, which is for just one account number (v_tosdef) along with the other parameters. I'm wondering if there's a problem with your input data. With 6M in your first table, your FOR ALL ENTRIES statement will be executed 1.2 million times. Tyically the database interface breaks down your Select-For All entries statement into 5 records per query. Again, run ST05 and you will see this.
In SE16, on your BSIS table, what is your count of records if you enter only the account number?
As a test, you might want to try entering all your parameters in SE16, run ST05 to trace the SQL to see what it is doing. You may have to kill your SE16 session or it may time out on you. You can stop your ST05 trace before your SE16 finishes and it will still show how SAP is going after the data and what index it used.
Let me know if this helped any.
Regards,
Filler -
Select For all entries with multiple keys
Dear Developers,
im writing a program which reads the last the last mseg entry with bwart 101 and bwart 201 an writes it into different fields of a table. In dependance of the bwart the max-value of mkpf-budat should be moved into field wedat or wadat.
At the moment i use this coding:
loop at gt_daten assigning <fs_daten>.
select distinct max( budat ) from wb2_v_mkpf_mseg2 into <fs_daten>-wedat
where matnr_i = <fs_daten>-matnr
and werks_i = <fs_daten>-werks
and lgort_i = <fs_daten>-lgort
and bwart_i = '101'.
select distinct max( budat ) from wb2_v_mkpf_mseg2 into <fs_daten>-wadat
where matnr_i = <fs_daten>-matnr
and werks_i = <fs_daten>-werks
and lgort_i = <fs_daten>-lgort
and bwart_i = '201'.
endloop.
wb2_v_mkpf_mseg2 is a view combining mkpf an mseg by primary keys.
Searching the internet i read, using FOR ALL ENTRIES should be prefered to selectstatements in loops.
So i tried:
*selectstatement
select budat matnr_i werks_i lgort_i bwart_i from wb2_v_mkpf_mseg2 into table lt_mseg for all entries in gt_daten
where matnr_i = gt_daten-matnr
and werks_i = gt_daten-werks
and lgort_i = gt_daten-lgort
and ( bwart_i = '101' or bwart_i = '201' )
*Substitute the MAX( )-Function
sort lt_mseg descending by matnr werks lgort bwart budat.
delete adjacent duplicates from lt_mseg comparing matnr werks lgort bwart.
*Differ between wedat and wadat
loop at gt_daten assigning <fs_daten>.
loop at lt_mseg assigning <fs_mseg>
where matnr = <fs_daten>-matnr
and werks = <fs_daten>-werks
and lgort = <fs_daten>-lgort.
case <fs_mseg>-bwart.
when '101'.
<fs_daten>-wedat = <fs_mseg>-budat.
when '201'.
<fs_daten>-wadat = <fs_mseg>-budat.
endcase.
endloop.
Even in the dev-system this takes twice the time of the "nested" selects.
Imho this is because of the internal OR interpretation of the FOR ALL ENTRIES-statement and the size of the result.
Can somebody give me a hint, how to tune this code?
Select Inner join should be difficult because the target field differs, dependent of the value in bwart...
Thanks in advance!I understand that you are trying to capture the maximum value of posting date MKPF-BUDAT for movement types 101 and 201 for each combination of material, plant and storage location.
Few things, that makes the below coding more efficient at both application and database level and I confirmed this on an IDES sandbox
1. Along with MKPF and MSEG, there is another table WBGT, in the view WB2_V_MKPF_MSEG join and also WBGT has select condition restrictions imposed on its fields. So if this restriction impacts your selection you may want to do a INNER JOIN of MSEG with MKPF only (with MSEG as leading table, as it has an active secondary index with MATNR, WERKS, LGORT and BWART ) and also there won't be overhead from the unnecessary join with WBGT table whose fields you are not using.
2. The below SORT on lt_mseg will ensure that the record having greatest BUDAT will be at the top of all rows (least index) for each combination of MATNR, WERKS, LGORT and BWART.
3. DELETE ADJACENT DUPLICATES will ensure that only the top row (having greatest BUDAT) remains in the table lt_mseg for each combination of MATNR, WERKS, LGORT and BWART. This will ensure that subsequent READs with BINARY SEARCH will always and efficiently read the row with maximum value of BUDAT for each unique combination of MATNR, WERKS, LGORT and BWART.
4. The below logic will require more memory (even though it is more efficient performance wise) compared to direct SELECT with MAX for each MATNR, WERKS, LGORT and BWART in a LOOP the way you were doing before. So if the size of lt_mseg is causing memory issues, your logic with aggregate function MAX at database level will be your only option.
So, I propose you revise your coding like below for most optimal results
CHECK NOT gt_daten[] IS INITIAL.
*selectstatement
*SELECT budat matnr_i werks_i lgort_i bwart_i
* FROM wb2_v_mkpf_mseg2
* INTO TABLE lt_mseg
* FOR ALL ENTRIES IN gt_daten
* WHERE matnr_i = gt_daten-matnr
* AND werks_i = gt_daten-werks
* AND lgort_i = gt_daten-lgort
* AND ( bwart_i = '101' OR bwart_i = '201' ).
* The below SELECT is more economical than the one commented above
SELECT mkpf~budat mseg~matnr mseg~werks mseg~lgort mseg~bwart
FROM mseg INNER JOIN mkpf
ON mseg~mblnr = mkpf~mblnr AND
mseg~mjahr = mkpf~mjahr
INTO TABLE lt_mseg
FOR ALL ENTRIES IN gt_daten
WHERE mseg~matnr = gt_daten-matnr
AND mseg~werks = gt_daten-werks
AND mseg~lgort = gt_daten-lgort
AND ( mseg~bwart = '101' OR mseg~bwart = '201' ).
*Substitute the MAX( )-Function
SORT lt_mseg BY matnr werks lgort bwart DESCENDING budat.
DELETE ADJACENT DUPLICATES FROM lt_mseg COMPARING matnr werks lgort bwart.
*Differ between wedat and wadat
LOOP AT gt_daten ASSIGNING <fs_daten>.
READ TABLE lt_mseg ASSIGNING <fs_mseg>
WITH KEY matnr = <fs_daten>-matnr
werks = <fs_daten>-werks
lgort = <fs_daten>-lgort
bwart = '101' BINARY SEARCH.
IF sy-subrc = 0.
<fs_daten>-wedat = <fs_mseg>-budat.
ENDIF.
READ TABLE lt_mseg ASSIGNING <fs_mseg>
WITH KEY matnr = <fs_daten>-matnr
werks = <fs_daten>-werks
lgort = <fs_daten>-lgort
bwart = '201' BINARY SEARCH.
IF sy-subrc = 0.
<fs_daten>-wadat = <fs_mseg>-budat.
ENDIF.
ENDLOOP. -
Why should we select all key fields when using for all entries
Hi,
Why should we select all key fields in our select query when using for all entries statement?
I read about for all entries but this point was not clear in any post.
Please explain me
Regards,
SubhashiniDear Subhasini,
It is because FOR ALL ENTRIES deletes the duplicate entries before populating the target internal table.
Please do an F1 on FOR ALL ENTRIES & read the SAP documentation.
I mean how duplicate entries will not get deleted when we use this?
Quite simple, if you select all key fields then each entry will be unique & there will not be any duplicate entries to delete !!
BR,
Suhas
Edited by: Suhas Saha on Oct 16, 2009 9:41 AM -
Maximum number of records for usage of "For all entries"
Hi,
Is there a limit on maximum number of records to be selected from the database using "For all entries" statement ?
Thanks in advanceThere is a UNDOCUMENTED(??) behaviousr
FOR ALL ENTRIES does ahidden SELECT DISTINCT & drops duplicates.
http://web.mit.edu/fss/dev/abap_review_check_list.htm
3 pitfalls
"FOR ALL ENTRIES IN..." (outer join) are very fast but keep in the mind the special features and 3 pitfalls of using it.
(a) Duplicates are removed from the answer set as if you had specified "SELECT DISTINCT"... So unless you intend for duplicates to be deleted include the unique key of the detail line items in your select statement. In the data dictionary (SE11) the fields belonging to the unique key are marked with an "X" in the key column.
^^!!!!
(b) If the "one" table (the table that appears in the clause FOR ALL ENTRIES IN) is empty, all rows in the "many" table (the table that appears in the SELECT INTO clause ) are selected. Therefore make sure you check that the "one" table has rows before issuing a select with the "FOR ALL ENTRIES IN..." clause.
(c) If the 'one' table (the table that appears in the clause FOR ALL ENTRIES IN) is very large there is performance degradation Steven Buttiglieri created sample code to illustrate this. -
I wrote the code like is this correct is it is code is correct , i am not using the is initial statement before using the for all entries statement but it will show the same results, in this code any mistakes can any one plz modify and give the correct code. THANKS in Advance
DATA : BEGIN OF i_sales OCCURS 5,
vbeln LIKE vbak-vbeln,
erdat LIKE vbak-erdat,
netwr LIKE vbak-netwr,
END OF i_sales.
DATA: BEGIN OF itab OCCURS 0,
vbeln LIKE vbap-vbeln,
posnr LIKE vbap-posnr,
matnr LIKE vbap-matnr,
END OF itab.
SELECT-OPTIONS sno FOR i_sales-vbeln.
SELECT vbeln
erdat
netwr
INTO TABLE i_sales
FROM vbak
where vbeln in sno.
*LOOP AT i_sales.
WRITE:/ i_sales-vbeln,i_sales-erdat,i_sales-netwr.
*ENDLOOP.
select vbeln
posnr
matnr
INTO TABLE itab
FROM vbap
FOR ALL ENTRIES IN i_sales
WHERE vbeln = i_sales-vbeln.
LOOP AT itab.
WRITE:/ itab-vbeln,itab-posnr,itab-matnr.
ENDLOOP.Hi,
It is mandatory to check the driver table is initial or not before using FOR ALL ENTRIES. Other wise it will select all the data from the table VBAP.
In ur case it might worked because VBAP(Item table) will contain records only if VBAK(header table) has a record.
U can check ur results by making i_sales table empty. i.e. in selection screen give some wrong sales order numbers which doesn't exist in VBAK table and check ur result.
Check below the effective way of coding.
SELECT vbeln
erdat
netwr
INTO TABLE i_sales
FROM vbak
where vbeln in sno.
*LOOP AT i_sales.
WRITE:/ i_sales-vbeln,i_sales-erdat,i_sales-netwr.
*ENDLOOP.
i_salestemp[] = i_sales[].
SORT i_salestemp BY VBELN.
DELETE ADJACENT DUPLICATES FROM i_sales COMPARING vbeln.
CHECK NOT i_salestemp[] IS INITIAL.
select vbeln
posnr
matnr
INTO TABLE itab
FROM vbap
FOR ALL ENTRIES IN i_salestemp
WHERE vbeln = i_salestemp-vbeln.
LOOP AT itab.
WRITE:/ itab-vbeln,itab-posnr,itab-matnr.
ENDLOOP.
Thanks,
Vinod.
Edited by: Vinod Vemuru on Feb 29, 2008 7:22 PM -
For All Entries is NOT better than INNER JOIN in most cases
I quote from Siegfried Boes' excellent post here: Will writing an inner join be better or creating a view?
For all the FOR ALL ENTRIES lovers ... there is no proof for these reappearing recommendation.
There is nearly nobody who receives forum points, who recommends FOR ALL ENTRIES instead of Joins. What is the reason ???
It is easier to prove the opposite. A Join is a nested loop inside the database, a FOR ALL ENTRIES is partly outside of the database. FOR ALL ENTRIES works in blocks, joins on totals.
FOR ALL ENTRIES are not recommded on really large tables, because the chances are too high that
too many records are transferred.
People prefer FOR ALL ENTRIES, because JOINs are not so easy to understand. Joins can go wrong, but with a bit of understanding they can be fixed.
Some Joins are slow and can not be fixed, but then the FOR ALL ENTRIES would be extremely slow.
There are several kinds of views:
- projection views, i.e. only one table involved just fields reduced
- join views, several tables, joins conditions stored in dictionary
- materialized views, here the joined data are actually stored in the database. Storing and synchronisation has to be done manually.
Only the last one creates real overhead. It should be the exception.
Join Views and Joins are nearly identical. The view is better for reuse. The join is better in complicated, becuase if the access goes wrong, it can often be fixed by adding a hint. Hints can not be added to views.
Abraham Bukit points out:
If it is cluster table, (you can't use join). If it is buffered table, I would also say avoid join.
If they all are transaction table which are not buffered and are not cluster tables.
He further supports Siegfried's statement that FAE is easier to undestand than INNER JOINs.
Thomas Zloch says, regarding buffered tables:
At least think twice, maybe compare runtimes if in doubt.
So, unless someone has some EVIDENCE that FOR ALL ENTRIES is better, I don't think we want to see this discussed further.
Kind regards
MattTo give food for thought here's an example I gave in a thread:
If you have a statement like
SELECT ... FOR ALL ENTRIES IN FAE_itab WHERE f = FAE_itab-f.
SAP sends it to the database depending how the parameter rsdb/prefer_union_all is set:
rsdb/prefer_union_all = 0 =>
SELECT ... WHERE f = FAE_itab[1]-f
OR f = FAE_itab[2]-f
OR f = FAE_itab[N]-f
You have some influence of the generated statement type: Instead of OR'ed fields an IN list can be used
if you have only a single coulmn N to compare:
rsdb/prefer_in_itab_opt parameter:
SELECT ... WHERE f IN (itab[1]-f, itab[2]-f, ..., itab[N]-f)
rsdb/prefer_union_all = 1 =>
SELECT ... WHERE f = FAE_itab[1]-f
UNION ALL SELECT ... WHERE f = FAE_itab[2]-f
UNION ALL SELECT ... WHERE f = FAE_itab[N]-f
see: Note 48230 - Parameters for the SELECT ... FOR ALL ENTRIES statement
As you can see for the 2nd parameter several statements are generated and combined with a UNION ALL,
the first setting generates statements with OR's (or uses IN if possible) for the entries in FAE_itab.
I give you a little example here (my parameters are set in a way that the OR's are translated to IN lists; i traced the execution in ST05)
Select myid into table t_tabcount from mydbtable
for all entries in t_table " 484 entries
where myid = t_table-myid .
ST05 trace:
|Transaction SEU_INT|Work process no 0|Proc.type DIA|Client 200|User |
|Duration |Obj. name |Op. |Recs.|RC |Statement|
| 640|mydbtable |PREPARE| | 0|SELECT WHERE "myid" IN ( :A0 , :A1 , :A2 , :A3 , :A4 ) AND "myid" = :A5|
| 2|mydbtable |OPEN | | 0|SELECT WHERE "myid" IN ( 1 , 2 , 3 , 4 , 5 ) AND "myid" = 72 |
| 2.536|mydbtable |FETCH | 0| 1403| |
| 3|mydbtable |REOPEN | | 0|SELECT WHERE "myid" IN ( 6 , 7 , 8 , 9 , 10 ) AND "myid" = 72 |
| 118|mydbtable |FETCH | 0| |
| 2|mydbtable |REOPEN | | 0|SELECT WHERE "myid" IN ( 11 , 12 , 13 , 14 , 15 ) AND "myid" = 72 |
| 3|mydbtable |REOPEN | | 0|SELECT WHERE "myid" IN ( 475 , 476 , 477 , 478 , 479 ) AND "myid" = 72 |
| 94|mydbtable |FETCH | 0| 1403| |
| 2|mydbtable |REOPEN | | 0|SELECT WHERE "myid" IN ( 480 , 481 , 482 , 483 , 484 ) AND "myid" = 72 |
You see the IN list contained 5 entries each , wich made up about 97 statements for all 484 entries.
For every statment you have a single fetch operation wich means a separate access to the database.
If you would replace the FAE with a join you would only have one fetch to the database.
With the example above we can derive these observations:
1. From database point of view these settings kill performance when you access a big table and/or have a lot of entries or columns in your FAE_itab. Furthermore, you hide information what data you will access
at all and thus you block the database from creating a more efficient execution plan because it DOESN'T KNOW wich data you will select in the next step. I.e. it may be more efficient to scan the table in one shot instead of having many index accesses - but the database can make this decision only if it can examine ONE statement that has ALL the information of what data to retrieve.
2. A second impact is that with every statement execution you trigger the allocation of database resources
wich will contribute to the overhead described above.
Said that, FAE can never be a replacement for joining big tables (think of having a table with thousands of records in a FAE table )
Edited by: kishan P on Nov 2, 2010 2:16 PM - Format Fixed -
I was under the impression that, while getting data from database table 'for all entries' always imporves performance. Since we are not getting whole database table data. I was doing a select statement and I have used for all entries. I have only 20,000 records in the internal table. While selecting data from database table, it took more than one hour and timed out.
Latter, I hard coded some values and query worked and it just took few minutes.
So, do we need to avoid for all entries? What the best practice?
For more details Please check the code:
Source package has only 20,000 records and while getting data it timed out. So I commented for all entries and hardcoded the values. This time it took only few minutes. Can any one suggest the best practice for handling such things?
IF SOURCE_PACKAGE[] IS NOT INITIAL.
SELECT
CALMONTH
CALYEAR
COMPANY
/BIC/XPROF_CTR
PCOMPANY
/BIC/ZPRODASGN
/BIC/ZSLSRPTCD
CURKEY_TC
UNIT
GL_ACCOUNT
MATERIAL
FUNC_AREA
COSTCENTER
WBS_ELEMT
CURKEY_LC
/BIC/ZTEMPKEY
QUANTITY
/BIC/ZAMT_REP
/BIC/ZSALETYP
FROM
/BIC/AZGMROA1400
INTO TABLE IT_SOURCE_TMP
FOR ALL ENTRIES IN SOURCE_PACKAGE
WHERE
CALMONTH BETWEEN CMONTH1 AND CMONTH2 AND
CALYEAR = CURR_YEAR AND
COMPANY = SOURCE_PACKAGE-COMPANY AND
/BIC/XPROF_CTR = SOURCE_PACKAGE-/BIC/XPROF_CTR AND
PCOMPANY = SOURCE_PACKAGE-PCOMPANY AND
/BIC/ZPRODASGN = SOURCE_PACKAGE-/BIC/ZPRODASGN AND
/BIC/ZSLSRPTCD = SOURCE_PACKAGE-/BIC/ZSLSRPTCD AND
CURKEY_TC = SOURCE_PACKAGE-CURKEY_TC AND
UNIT = SOURCE_PACKAGE-UNIT AND
GL_ACCOUNT = SOURCE_PACKAGE-GL_ACCOUNT AND
MATERIAL = SOURCE_PACKAGE-MATERIAL AND
/BIC/ZSALETYP in ('TS', 'CG', 'IS', 'IC',
'TO', 'FG', 'OD', 'SS',
'RD', 'I3', 'D1', 'D2',
'D3', 'MS', 'PF', 'RA') .
FUNC_AREA = SOURCE_PACKAGE-FUNC_AREA AND
COSTCENTER = SOURCE_PACKAGE-COSTCENTER AND
WBS_ELEMT = SOURCE_PACKAGE-WBS_ELEMT AND
CURKEY_LC = SOURCE_PACKAGE-CURKEY_LC and
/BIC/ZACCOUNT = SOURCE_PACKAGE-/BIC/ZACCOUNT .
ENDIF.Hi,
if you have a statement like
SELECT ... FOR ALL ENTRIES IN FAE_itab WHERE f = FAE_itab-f.
SAP sends it to the database depending how the parameter rsdb/prefer_union_all is set:
rsdb/prefer_union_all = 0 =>
SELECT ... WHERE f = FAE_itab[1]-f
OR f = FAE_itab[2]-f
OR f = FAE_itab[N]-f
You have some small influence of the number of generated statements in the case of OR'ed taht an IN list should be used by
rsdb/prefer_in_itab_opt parameter:
SELECT ... WHERE f IN (itab[1]-f, itab[2]-f, ..., itab[N]-f)
rsdb/prefer_union_all = 1 =>
SELECT ... WHERE f = FAE_itab[1]-f
UNION ALL SELECT ... WHERE f = FAE_itab[2]-f
UNION ALL SELECT ... WHERE f = FAE_itab[N]-f
see: Note 48230 - Parameters for the SELECT ... FOR ALL ENTRIES statement
As you can see that the last setting generates several statements and combine them with a UNION ALL,
the first setting generates a statement with OR's (or uses IN list) for the entries in FAE_itab.
I give you a little example here (my parameters are set in a way that the OR's are translated to IN lists; i traced the execution in ST05)
Select myid into table t_tabcount from mydbtable
for all entries in t_table " 484 entries
where myid = t_table-myid
and myid = 72.
ST05 trace:
|Transaction SEU_INT|Work process no 0|Proc.type DIA|Client 200|User |
|Duration |Obj. name |Op. |Recs.|RC |Statement |
| 640|mydbtable |PREPARE| | 0|SELECT WHERE "myid" IN ( :A0 , :A1 , :A2 , :A3 , :A4 ) AND "myid" = :A5 |
| 2|mydbtable |OPEN | | 0|SELECT WHERE "myid" IN ( 1 , 2 , 3 , 4 , 5 ) AND "myid" = 72 |
| 2.536|mydbtable |FETCH | 0| 1403| |
| 3|mydbtable |REOPEN | | 0|SELECT WHERE "myid" IN ( 6 , 7 , 8 , 9 , 10 ) AND "myid" = 72 |
| 118|mydbtable |FETCH | 0| 1403| |
| 2|mydbtable |REOPEN | | 0|SELECT WHERE "myid" IN ( 11 , 12 , 13 , 14 , 15 ) AND "myid" = 72 |
| 3|mydbtable |REOPEN | | 0|SELECT WHERE "myid" IN ( 475 , 476 , 477 , 478 , 479 ) AND "myid" = 72 |
| 94|mydbtable |FETCH | 0| 1403| |
| 2|mydbtable |REOPEN | | 0|SELECT WHERE "myid" IN ( 480 , 481 , 482 , 483 , 484 ) AND "myid" = 72 |
You see the IN list contained 5 entries each , wich made up about 97 statements for all 484 entries.
From database point of view these settings kill performance when you have a lot of entries and/or
a lot of columns in your FAE_itab.
Said that, FAE i.e. can never be a replacement for joining big tables (think of having a table with thousands of records in a FAE table like you had)
If you say now that you completly threw away the FAE table of 20.000 entries it is no wonder
that it performs better. 20.000 records is not a small number if you create a lot of UNION's or OR's / IN lists that way!
Your original statement is a good example for the abuse of a FAE. In the SAP Notes this is the core problem with FAE besides empty FAE tables.
It's safe to use a FAE_itab table if the expected entries count is small (i.e. << 100).
What you have to decide is if it's more advantagous to
retrieve the FAE_tabs data once and executing other statements with the SAME FAE table in the same program to reuse it
or having additional roundtrips to the database if you don't use FAE tables at all
Bye
yk -
FOR ALL ENTRIES IN with two tables
Hi Guy's,
I have two int. tables, gt_likp, gt_lips.
I need to use "FOR ALL ENTRIES IN" with this two tables.
SELECT matnr
vkorg
vtweg
ypcogsl
FROM mvke
INTO TABLE gt_mvke
<b> "FOR ALL ENTRIES IN gt_likp gt_lips"</b>
WHERE matnr = gwa_liefpos_tab-matnr
AND vkorg = gt_likp-vkorg
AND vtweg = gt_lips-vtweg.
How to do this?
Please Help.
Thanks in Advance.Hi,
Fill gt_likp-vkorg values in a range(r_vkorg). Use gt_lips in FOR ALL ENTRIES.
Basically you can use only 1 internal table with FOR ALL ENTRIES statement.
SELECT matnr
vkorg
vtweg
ypcogsl
FROM mvke
INTO TABLE gt_mvke
FOR ALL ENTRIES IN gt_lips
WHERE matnr = gwa_liefpos_tab-matnr
AND vkorg in r_vkorg
AND vtweg = gt_lips-vtweg.
- SRao
Maybe you are looking for
-
Skillbuilders modal page help needed
Hello, I have installed the Skillbuilders modal page plugin on my workspace. (APEX4.2) I did all the default steps: - simple interactive report with create button - dynamic action When I click on 'create' something pops up, but it's not something I w
-
Error when using dbms_pumpdata to export data
DECLARE l_dp_handle NUMBER; BEGIN l_dp_handle := DBMS_DATAPUMP.open (operation => 'EXPORT', job_mode => 'TABLE'); dbms_datapump. add_file (handle => l_dp_handle , filename =>
-
Problem removing focused object from a table
Hi. I have a problem removing a component that is focused from a table. The whole row is removed except a single component (JSpinner) in one row. My table has three columns, the first two are String fields (not editable) and the last is a JSpinner. S
-
Since the iPad came out, there have been a lot of talk about the iBooks or iBookstore application whereas you could purchase and download ebooks for the use of the iPad. I think it would be nice for Apple to do the same for there systems through iTun
-
I bought a MAC on ebay and it came installed w/Snow Leopard. I need Quicktime 7 for its export utilities. I looked in my utility folder but there's no QT 7 there! I don't have the Snow Leopard install discs as the seller did not provide. How can I ge