Folgende Benutzer bedankten sich beim Autor ralf.wenzel für den Beitrag:
cuncon
Code: Alles auswählen.
*1.Schleife
LOOP AT gt_output ASSIGNING <gs_output>.
CALL FUNCTION 'MD_STOCK_REQUIREMENTS_LIST_API'
EXPORTING
* PLSCN =
MATNR = <gs_output>-matnr
WERKS = '1000'
* BERID =
* ERGBZ =
* AFIBZ =
* INPER =
* DISPLAY_LIST_MDPSX =
* DISPLAY_LIST_MDEZX =
* DISPLAY_LIST_MDSUX =
* NOBUF =
* PLAUF =
IMPORTING
* E_MT61D =
E_MDKP = gs_mdkp
* E_CM61M =
* E_MDSTA =
* E_ERGBZ =
TABLES
* MDPSX =
MDEZX = gt_bestandliste
* MDSUX =
EXCEPTIONS
MATERIAL_PLANT_NOT_FOUND = 1
PLANT_NOT_FOUND = 2
OTHERS = 3
.
IF SY-SUBRC <> 0.
MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ELSE.
gs_output-hoebe = gs_mdkp-hoebe.
CLEAR gs_mdkp.
SORT gt_bestandliste BY delb0 DESCENDING.
DELETE gt_bestandliste WHERE delb0 = 'AR-RES'.
gt_bestandliste_temp[] = gt_bestandliste[].
*2.Schleife
LOOP AT gt_bestandliste ASSIGNING <gs_bestandliste> WHERE delb0 = 'W-BEST' OR delb0 = 'KD-BST' OR delb0 = 'K-AUFT' OR delb0 = 'LIEFER' OR delb0 = 'SK-BED'.
IF <gs_bestandliste>-delb0 = 'W-BEST'.
gs_output-wbmng02 = <gs_bestandliste>-mng02.
ENDIF.
IF <gs_bestandliste>-delb0 = 'KD-BST'.
<gs_output>-sum_kb = <gs_output>-sum_kb + <gs_bestandliste>-mng02.
*Kennzeichen"X" setzen,wenn mindestens ein negativer Kundenauftragsbestand vorliegt
IF <gs_bestandliste>-mng02 < 0.
<gs_output>-nkbflag = 'X'.
ENDIF.
"Kennzeichen "X" setzen, wenn Kundenauftragsbestände ohne Vorgang existieren, dh, wenn mng01 <> 0 und nächste Eintrag ist auch KD-BST und hat nicht gleiche planr
IF <gs_bestandliste>-mng01 <> 0.
IF <gs_output>-ovflag IS INITIAL.
i = best_idx + 1.
READ TABLE gt_bestandliste_temp INDEX i INTO gs_bestandliste_temp.
IF sy-subrc = 0.
IF gs_bestandliste_temp-planr <> <gs_bestandliste>-planr.
<gs_output>-ovflag = 'X'.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
IF <gs_bestandliste>-delb0 = 'K-AUFT'.
<gs_output>-sum_bdm_kauf = <gs_output>-sum_bdm_kauf + <gs_bestandliste>-mng01.
ENDIF.
IF <gs_bestandliste>-delb0 = 'LIEFER'.
<gs_output>-sum_bdm_liefer = <gs_output>-sum_bdm_liefer + <gs_bestandliste>-mng01.
ENDIF.
IF <gs_bestandliste>-delb0 = 'SK-BED'.
<gs_output>-sum_bdm_sek = <gs_output>-sum_bdm_sek + <gs_bestandliste>-mng01.
ENDIF.
CLEAR <gs_bestandliste>-mng01.
CLEAR <gs_bestandliste>-mng02.
ENDLOOP.
ENDIF.
CLEAR gt_bestandliste_temp. REFRESH gt_bestandliste_temp.
CLEAR gt_mdez_sum. REFRESH gt_mdez_sum.
CLEAR gt_mdez. REFRESH gt_mdez.
ENDIF.
ENDLOOP.
Folgende Benutzer bedankten sich beim Autor ralf.wenzel für den Beitrag:
cuncon
ich habe gerade bei mir gesehen, wir haben ERP 6.0.zzcpak hat geschrieben:nur mal als Verdacht, da ich nicht weiß, unter welchem Release-Stand dein Programm arbeitet.
Der Funktionsbaustein MD_STOCK_REQUIREMENTS_LIST_API hatte mal den Fehler, alte Daten zu liefern. Ursache war ein fehlendes CLEAR/REFRESH auf die Tabellenparameter des Funktionsbausteines.
Siehe dazu SAP-Hinweis https://launchpad.support.sap.com/#/corrins/396372/1
Der ist allerdings steinalt und für 46B/46C gültig. Aber es soll ja noch solche Installationen geben, auch produktiv.
Sonst prüf doch spaßeshalber mal im Debugger, ob deine interne Tabelle GT_BESTANDSLISTE auch noch die Daten des vorigen Laufes enthält, bzw. ob diese im Funktionsbaustein geleert wird.
Ich habe auch geprüft bei Debugger, dass es bei jedem Lauf die Tabelle GT_BESTANDSLISTE neu erfüllt wird, dh. die alten Daten waren wirklich weg. Aber zur Sicherheit mache ich sie leer vor dem Übergeben.zzcpak hat geschrieben:nur mal als Verdacht, da ich nicht weiß, unter welchem Release-Stand dein Programm arbeitet.
Der Funktionsbaustein MD_STOCK_REQUIREMENTS_LIST_API hatte mal den Fehler, alte Daten zu liefern. Ursache war ein fehlendes CLEAR/REFRESH auf die Tabellenparameter des Funktionsbausteines.
Siehe dazu SAP-Hinweis https://launchpad.support.sap.com/#/corrins/396372/1
Der ist allerdings steinalt und für 46B/46C gültig. Aber es soll ja noch solche Installationen geben, auch produktiv.
Sonst prüf doch spaßeshalber mal im Debugger, ob deine interne Tabelle GT_BESTANDSLISTE auch noch die Daten des vorigen Laufes enthält, bzw. ob diese im Funktionsbaustein geleert wird.
Hallo Ralf,ralf.wenzel hat geschrieben:Ich hab gerade nur begrenzt Zeit, aber ich hab mal draufgeguckt, ob mir was auffällt. Ein paar Dinge sind mir aufgefallen.
Die Bestandsliste ist eine Standardtabelle, weil sie als solche aus dem Funktionsbaustein rauskommt - ich würde sie umkopieren in eine Tabelle mit einem entsprechenden Schlüssel auf DELB0. Außerdem würde ich darauf achten, dass die MATNR in GT_OUTPUT jeweils einmalig ist (damit du nicht für dieselbe Mateiralnummer das Zeugs mehrfach durchläufst).
Wenn man länger guckt, findet man sicher noch mehr
Zum Beispiel KÖNNTE man die Bestandslisten in einer großen Tabelle sammeln (insert linse of gt_bestandsliste into table gt_bestandsliste_gesamt, über DIE machst du dann den LOOP), je größer die Tabelle ist, umso eher bringen die Schlüssel was, würde ich meinen.
Insbesondere kannst du die beiden LOOPs dann hintereinander machen und musst sie nicht "ineinander" machen. Zu den Feldsymbolen: Es gibt in meinen Augen keinen Grund, KEINE Feldsymbole zu verwenden und je größer die Tabellen sind, umso eher bringen Feldsymbole was.
Das wären also meine drei ersten Tipps: Auf einmalige MATNRn achten, im LOOP AT gt_output nur den FuBau aufrufen und die gt_bestandsliste sammeln einer großen itab, die einen entsprechenden Schlüssel haben sollte, damit der LOOP AT WHERE auch wirklich nur für die Sätze angesprungen wird, für den die WHERE Bedingung auch gilt und die LOOPs hintereinander machen statt "ineinander".
Ralf
Mal abgesehen von der Performance. Wenn der Code das tun soll, was in dem Kommentar gesagt wird, dann tut er das nur zufällig. Grund: Du fragst nicht ab ob die folgende Zeile auch "KD-BST" ist. Außerdem die Frage: Ist garantiert, dass das Sortieren und Löschen das du machst die Reihenfolge die der FuBa zurückgegeben hat nicht ändert?cuncon hat geschrieben:Code: Alles auswählen.
"Kennzeichen "X" setzen, wenn Kundenauftragsbestände ohne Vorgang existieren, dh, wenn mng01 <> 0 und nächste Eintrag ist auch KD-BST und hat nicht gleiche planr
Folgende Benutzer bedankten sich beim Autor black_adept für den Beitrag:
cuncon
Ich werde das noch mal kucken. Dankeblack_adept hat geschrieben:Mal abgesehen von der Performance. Wenn der Code das tun soll, was in dem Kommentar gesagt wird, dann tut er das nur zufällig. Grund: Du fragst nicht ab ob die folgende Zeile auch "KD-BST" ist. Außerdem die Frage: Ist garantiert, dass das Sortieren und Löschen das du machst die Reihenfolge die der FuBa zurückgegeben hat nicht ändert?cuncon hat geschrieben:Code: Alles auswählen.
"Kennzeichen "X" setzen, wenn Kundenauftragsbestände ohne Vorgang existieren, dh, wenn mng01 <> 0 und nächste Eintrag ist auch KD-BST und hat nicht gleiche planr
Code: Alles auswählen.
SORT gt_bestandliste BY delb0 DESCENDING.
DELETE gt_bestandliste WHERE delb0 = 'AR-RES'.
Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag:
cuncon
Hallo DeathAndPain,DeathAndPain hat geschrieben:Also das ist alles noch keine zufriedenstellende Erklärung. Was Du da im inneren LOOP machst, ist performancetechnisch eigentlich ein Lacher. Das sollte nicht auf einen Timeout laufen, selbst wenn gt_bestandliste 60.000 Einträge hätte! Da muss noch irgendwo anders der Hund begraben sein.
Allerdings finde ich den Inhalt der Tabelle gt_bestandliste gar nicht so interessant, denn der ändert sch ja mit jedem Durchlauf der äußeren Tabelle. Wieviel ist denn in gt_output drin? Das ist doch viel wichtiger, denn das multipliziert sich ja mit den jeweiligen Einträgen aus gt_bestandliste aus! Im übrigen wird der Funktionsbaustein so oft durchlaufen, wie gt_output Zeilen hat. Und den FB habe ich viel mehr im Verdacht, Laufzeit zu ziehen! Der wird vermutlich auch Datenbankzugriffe machen.
Die anderen Optimierungen sind nett, aber nur Kleinkram. Was Du dabei noch machen kannst:
Du sortierst die AR-RES-Zeilen erst aufwändig rein, um sie anschließend rauszulöschen. Würde ich gefühlsmäßig andersrum machen: Erst die unnützen Zeilen rauslöschen, und dann nur den interessanten Rest sortieren. Aber vielleicht ist Dein Weg sogar schneller, weil er so nur einmal sequenziell durch die Tabelle muss. Müsste man mal austesten. Hängt sicherlich auch davon ab, wie viele AR-RES-Zeilen es in der Tabelle gibt. Taugt aber auch nicht als zufriedenstellende Erklärung für Deinen Tmeout.Code: Alles auswählen.
SORT gt_bestandliste BY delb0 DESCENDING. DELETE gt_bestandliste WHERE delb0 = 'AR-RES'.
Aber wie Ralf schon sagte, ein LOOP WHERE hat (im Gegensatz zum READ TABLE mit BINARY SEARCH) nur dann etwas von einer Sortierung, wenn die Tabelle selbst als SORTED definiert ist. Dabei tunlichst genau den Tabellenschlüssel festlegen, mit dem Dein LOOP später suchen wird. Wobei ich befürchte, dass mit dem OR der Sortierungsvorteil auch wieder den Bach runtergeht; das wird der LOOP so nicht nutzen können. Der Aufzählungs-IN, den der SELECT-Befehl kennt, wird vom LOOP leider nicht unterstützt. Da müsstest Du Dir eine RANGES-Tabelle mit den möglichen Werten für delb0 aufbauen und dann LOOP AT gt_bestandsliste WHERE delbo IN deine_ranges_tabelle schreiben. Dann könnte die Optimierung klappen.
Ansonsten nochmal die Frage: War euer Systemstand nicht schon auf 7.40? (Herausfinden im SAPGui über Menü System -> Status, Klicken auf Lupe -> Release der Komponente SAP_ABA anschauen. Wenn ja, dann solltest Du Dir unbedingt einen grundlegend anderen Programmierstil angewöhnen. Dann ist Dein Codingstil nämlich als ziemlich veraltet einzuschätzen; das kann man mit den neuen Mitteln von 7.40 alles viel kürzer und schöner programmieren.
Aber wie gesagt, als erstes mal klären, wieviel Zeilen gt_output hat.