Ja hab ich.Krueger hat geschrieben:Wenn alles passt, dann leg ich nen View an
DEN kannst Dir DANN auch sparen
Dann schauts schöner aus
Hast Du Deinen JOIN wirklich schon über die 13 Millionen Einträge laufen lassen???
Hast Du mal eine Laufzeitanalyse mit dem JOIN (über die 13.....) und eine Select-Schleife laufen lassen.
Code: Alles auswählen.
SELECT d~posnr AS zposnr d~matnr AS bpmatnr d~arktx AS bparktx
d~kwmeng AS bpkwmeng d~netwr AS bpnetwr d~uepos AS bpuepos
FROM vbap AS d
INTO gs_all-zposnr gs_all-bpmatnr gs_all-bparktx gs_all-bpkwmeng
gs_all-bpnetwr gs_all-bpuepos
FOR ALL ENTRIES IN gt_vkbel
WHERE vbeln = gt_vkbel-vbeln.
ENDSELECT.
Code: Alles auswählen.
"GS_ALL-BPMATNR" konnte nicht interpretiert werden. Mögliche
Fehlerursachen: Falsche Schreibweise oder Kommafehler.
Wieso das?Krueger hat geschrieben:d~matnr AS bpmatnr
Eher so:
d~matnr d~bpmatnr ???
Code: Alles auswählen.
AS bpmatnr
Falsche Syntax bei INTO:MarkusW hat geschrieben: Wieso bekomm ich da nen Fehler? Da bleibt mir ja gar nix anderes übrig als CORRESPONDING FIELDS anzugeben...
Code: Alles auswählen.
SELECT d~posnr AS zposnr d~matnr AS bpmatnr d~arktx AS bparktx
d~kwmeng AS bpkwmeng d~netwr AS bpnetwr d~uepos AS bpuepos
FROM vbap AS d
INTO ( gs_all-zposnr, gs_all-bpmatnr, gs_all-bparktx, gs_all-bpkwmeng,
gs_all-bpnetwr, gs_all-bpuepos )
FOR ALL ENTRIES IN gt_vkbel
WHERE vbeln = gt_vkbel-vbeln.
ENDSELECT.
Code: Alles auswählen.
SELECT d~posnr AS zposnr d~matnr AS bpmatnr d~arktx AS bparktx
d~kwmeng AS bpkwmeng d~netwr AS bpnetwr d~uepos AS bpuepos
FROM vbap AS d
INTO ( gs_all-zposnr, gs_all-bpmatnr, gs_all-bparktx, gs_all-bpkwmeng,
gs_all-bpnetwr, gs_all-bpuepos )
FOR ALL ENTRIES IN gt_vkbel
WHERE vbeln = gt_vkbel-vbeln.
ENDSELECT.
Code: Alles auswählen.
SELECT d~posnr
d~matnr
d~arktx
d~kwmeng
d~netwr
d~uepos
FROM vbap AS d
INTO ( gs_all-zposnr, gs_all-bpmatnr,
gs_all-bparktx, gs_all-bpkwmeng,
gs_all-bpnetwr, gs_all-bpuepos )
FOR ALL ENTRIES IN gt_vkbel
WHERE vbeln = gt_vkbel-vbeln.
ENDSELECT.
Code: Alles auswählen.
SELECT posnr
matnr
arktx
kwmeng
netwr
uepos
FROM vbap
INTO ( gs_all-zposnr, gs_all-bpmatnr,
gs_all-bparktx, gs_all-bpkwmeng,
gs_all-bpnetwr, gs_all-bpuepos )
FOR ALL ENTRIES IN gt_vkbel
WHERE vbeln = gt_vkbel-vbeln.
ENDSELECT.
Code: Alles auswählen.
SELECT d~posnr AS zposnr d~matnr AS bpmatnr d~arktx AS bparktx
d~kwmeng AS bpkwmeng d~netwr AS bpnetwr d~uepos AS bpuepos
FROM vbap AS d
INTO ( gs_all-zposnr, gs_all-bpmatnr, gs_all-bparktx, gs_all-bpkwmeng,
gs_all-bpnetwr, gs_all-bpuepos )
FOR ALL ENTRIES IN gt_vkbel
WHERE vbeln = gt_vkbel-vbeln.
ENDSELECT.
Code: Alles auswählen.
SELECT d~posnr
d~matnr
d~arktx
d~kwmeng
d~netwr
d~uepos
FROM vbap AS d
INTO ( gs_all-zposnr, gs_all-bpmatnr,
gs_all-bparktx, gs_all-bpkwmeng,
gs_all-bpnetwr, gs_all-bpuepos )
FOR ALL ENTRIES IN gt_vkbel
WHERE vbeln = gt_vkbel-vbeln.
ENDSELECT.
Code: Alles auswählen.
SELECT posnr
matnr
arktx
kwmeng
netwr
uepos
FROM vbap
INTO ( gs_all-zposnr, gs_all-bpmatnr,
gs_all-bparktx, gs_all-bpkwmeng,
gs_all-bpnetwr, gs_all-bpuepos )
FOR ALL ENTRIES IN gt_vkbel
WHERE vbeln = gt_vkbel-vbeln.
ENDSELECT.
Danke...JHM hat geschrieben:Falsche Syntax bei INTO:MarkusW hat geschrieben: Wieso bekomm ich da nen Fehler? Da bleibt mir ja gar nix anderes übrig als CORRESPONDING FIELDS anzugeben...Code: Alles auswählen.
SELECT d~posnr AS zposnr d~matnr AS bpmatnr d~arktx AS bparktx d~kwmeng AS bpkwmeng d~netwr AS bpnetwr d~uepos AS bpuepos FROM vbap AS d INTO ( gs_all-zposnr, gs_all-bpmatnr, gs_all-bparktx, gs_all-bpkwmeng, gs_all-bpnetwr, gs_all-bpuepos ) FOR ALL ENTRIES IN gt_vkbel WHERE vbeln = gt_vkbel-vbeln. ENDSELECT.
Da hast du rechtKrueger hat geschrieben:Diese ganzen Aliase sind doch überflüssig???:
GrußJHM hat geschrieben:Weißt du ob der Index von der VBAK gezogen wird?MarkusW hat geschrieben: Wäre dankbar für weitere Tips und Hilfen!
Vielleicht ist ja hier einer da, der sich im SD-Bereich gut auskennt
evtl. mit ST05 einen SQL-Trace durchführen um das zu klären.
Weißt du welcher Select wie lange dauert?
evtl. mit se30 eine Laufzeitanalyse durchführen um den ungünstigen Select zu finden.
Schlecht zu lesen, aber es sind über 2million (ms) für den Select der VBAK.Code: Alles auswählen.
Dauer Objektname Oper Sätze RC Anweisung 0 VBAK REOPEN 0 SELECT WHERE "MANDT" = '001' AND "ERDAT" BETWEEN 20050101 AND 20050331 2.044.013 VBAK FETCH 75 1403
Ist ja richtig lang...vllt les ich den Trace aber auch falsch und die Zeit gilt auch für die VBAP
jeder einzelne Satz von der Likp/lips zu lesen dauert im schnitt 100000 ms.
Also erst recht ewig...
Der Select Single auf die KNA1 ist in meinen Augen ungünstig. Da über so_kunnr die Kunden eingegrenzt werden müssen, kann man sich die Daten auf einen Schlag in das Programm lesen und in einer itab zwischen speichern. Beim zusammen setzten der Daten mittels READ TABLE BINARY SEARCH aus der itab lesen oder zum Schluss einen LOOP über die itab_kunnr und die Ausgabetabelle mit einem MODIFY WHERE füllen.
KNA1 schmeiss ich raus...braucht kein mensch.
Der Select auf die likp/lips ist ungünstig, da kein Index auf vgbel/vgpos existiert. Evtl. ist es schneller sich voher die Schlüssel aus der VBFA zulesen und mit FOR ALL ENTRIES auf die LIKP/LIPS zugehen. (Bei FOR ALL ENTRIES auf Sortierung achten). Evtl. kannst du auf die VBFA schon mit FOR ALL ENTRIES gt_all gehen. Dann mit den gelesenen Lieferungsdaten auf die LIKP/LIPS auch mit FOR ALL ENTRIES gt_vbfa. Die Daten dann mittels READ BINARY SEARCH während dem erstellen der Ausgabetabelle dazu lesen.
Diesen Absatz musste mir mal erklären.
So sieht es bei mir derzeit aus:
In diesem Fall bekomme ich unter 100 Treffer. (Entwicklersystem)Code: Alles auswählen.
SELECT vbeln erdat kunnr auart vkbur vkorg vtweg INTO TABLE gt_vkbel FROM vbak WHERE erdat IN so_erdat AND kunnr IN so_kunnr AND auart IN so_auart AND vkbur IN so_vkbur AND vkorg IN so_vkorg AND vtweg IN so_vtweg. * LOOP AT gt_vkbel INTO gs_vkbel. SELECT d~posnr AS zposnr d~matnr AS bpmatnr d~arktx AS bparktx d~kwmeng AS bpkwmeng d~netwr AS bpnetwr d~uepos AS bpuepos FROM vbap AS d INTO (gs_all-zposnr, gs_all-bpmatnr, gs_all-bparktx, gs_all-bpkwmeng, gs_all-bpnetwr, gs_all-bpuepos) FOR ALL ENTRIES IN gt_vkbel WHERE vbeln = gt_vkbel-vbeln. gs_all-bavbeln = gs_vkbel-vbeln. gs_all-baauart = gs_vkbel-auart. gs_all-baerdat = gs_vkbel-erdat. gs_all-bakunnr = gs_vkbel-kunnr. gs_all-bavkbur = gs_vkbel-vkbur. gs_all-bavkorg = gs_vkbel-vkorg. gs_all-bavtweg = gs_vkbel-vtweg. APPEND gs_all TO gt_all. ENDSELECT. * ENDLOOP.
Setz ich den LOOP aktiv...bekomme ich 3500 Treffer. Bekomme dann eben alle Positionen zu einem Kopfsatz. Ich dachte das macht der Befehl FOR ALL ENTRIES?
Allein dadurch das ich ne Select-Schleife in einer Loop-Schleife hab ist ja schon klar das es ewig dauert...hab ich da nen Programmierfehler?
Aber nu zum eigentlichen...
Wie komme ich mit den Werten der VBAK,VBAP über die VBFA auf die LIKP/LIPS???
Hab mir die Tabellen mal angeschaut und ehrlich gesagt sind die scheisse dokumentiert...keine Ahnung welche Felder nun das Gegenstück zur VBELN von VBAK ist...sorry für die Ausdrucksweise.
Wäre gut wenn ich da mal die zusammengehörigen Felder weiß
Wenn ihr nicht pro Auftragsposition genau eine Lieferungsposition und genau eine Rechnungsposition habt arbeitet dein Programm nicht korrekt. Nur der erste Satz kann mit MODIFY übernommen werden, danach müsste mit APPEND ein neuer Satz in die Tabelle gt_all aufgenommen werden. Wenn du hier mit einer zweiten reinen Ausgabetabelle arbeiten würdest, könntest du alle Sätze mittels APPEND übernehmen und der DELETE würde überflüssig.
Öhm Ist das vllt das wo ich oben den Loop um die Selectschleife hab?
Oder versteh ich hier Bahnhof...
Die Abbruchbedingungen kommen viel zu spät. Wenn keine Lieferung gefunden wurde, muss erst garnicht nach einer Faktura gesucht werden.
Habe ich ausgebessert...lese den nächsten Satz mit CONTINUE.
Soweit meine Ideen
Du verstehst den FOR ALL ENTRIES falsch. Der FOR ALL ENTRIES ersetzt deine LOOP-Schleife über die gt_vkbel. Es wird quasi für jeden Eintrag in gt_vkbe ein SELECT durchgeführt. Mit dem LOOP hast du in gt_all die Sätze aus der vbap mehrfach drin.MarkusW hat geschrieben: Bekomme dann eben alle Positionen zu einem Kopfsatz. Ich dachte das macht der Befehl FOR ALL ENTRIES?
Ein Beispiel dann wird vieles klarer. Das Testprogramm vergleicht den JOIN gegen FOR ALL ENTRIES und mißt die Laufzeit. Ausgegeben werden die Anzahl der gelesenen Sätze und Laufzeit je Select. Die Verknüpfung über die VBFA wird auch klar.MarkusW hat geschrieben: Aber nu zum eigentlichen...
Wie komme ich mit den Werten der VBAK,VBAP über die VBFA auf die LIKP/LIPS???
Wäre gut wenn ich da mal die zusammengehörigen Felder weiß
Code: Alles auswählen.
REPORT ztest NO STANDARD PAGE HEADING.
TYPES: BEGIN OF t_all,
auart TYPE vbak-auart,
vbeln TYPE vbak-vbeln,
erdat TYPE vbak-erdat,
kunnr TYPE vbak-kunnr,
vkbur TYPE vbak-vkbur,
vkorg TYPE vbak-vkorg,
vtweg TYPE vbak-vtweg,
vbeln_li TYPE likp-vbeln,
erdat_li TYPE likp-erdat,
wadat_ist TYPE likp-wadat_ist,
matnr TYPE vbap-matnr,
arktx TYPE vbap-arktx,
kwmeng TYPE vbap-kwmeng,
netwr TYPE vbap-netwr,
uepos TYPE vbap-uepos,
lfimg TYPE lips-lfimg,
posnr TYPE lips-posnr,
bzirk TYPE vbkd-bzirk,
END OF t_all.
TYPES: BEGIN OF t_vbak,
vbeln TYPE vbak-vbeln,
posnr TYPE vbap-posnr,
auart TYPE vbak-auart,
erdat TYPE vbak-erdat,
kunnr TYPE vbak-kunnr,
vkbur TYPE vbak-vkbur,
vkorg TYPE vbak-vkorg,
vtweg TYPE vbak-vtweg,
matnr TYPE vbap-matnr,
arktx TYPE vbap-arktx,
kwmeng TYPE vbap-kwmeng,
netwr TYPE vbap-netwr,
uepos TYPE vbap-uepos,
bzirk TYPE vbkd-bzirk,
END OF t_vbak,
BEGIN OF t_vbfa,
vbeln TYPE vbfa-vbeln,
posnn TYPE vbfa-posnn,
END OF t_vbfa,
BEGIN OF t_likp,
vgbel TYPE lips-vgbel, "Referenz auf den Auftrag
vgpos TYPE lips-vgpos, "Referenz auf den Auftrag
* Daten der Lieferung
vbeln TYPE likp-vbeln,
posnr TYPE lips-posnr,
erdat TYPE likp-erdat,
wadat_ist TYPE likp-wadat_ist,
lfimg TYPE lips-lfimg,
END OF t_likp.
* Für die Zeitmessung
DATA: g_start TYPE i,
g_ende TYPE i,
g_diff TYPE i.
* Fürs Protokoll
DATA: g_anz TYPE i.
* Tabellen für die Selects
DATA: gt_all TYPE TABLE OF t_all,
gw_all TYPE t_all,
gt_vbak TYPE TABLE OF t_vbak WITH KEY vbeln posnr,
gw_vbak TYPE t_vbak,
gt_vbfa TYPE TABLE OF t_vbfa WITH KEY vbeln, posnn,
gw_vbfa TYPE t_vbfa,
gt_likp TYPE TABLE OF t_likp WITH KEY vgbel, vgpos,
gw_likp TYPE t_likp.
SELECT-OPTIONS:
so_auart FOR gw_all-auart OBLIGATORY,
so_erdat FOR gw_all-erdat OBLIGATORY,
so_vbeln FOR gw_all-vbeln,
so_kunnr FOR gw_all-kunnr,
so_vkbur FOR gw_all-vkbur,
so_vkorg FOR gw_all-vkorg,
so_vtweg FOR gw_all-vtweg,
so_matnr FOR gw_all-matnr,
so_uepos FOR gw_all-uepos,
so_bzirk FOR gw_all-bzirk,
so_lbeln FOR gw_all-vbeln,
so_lerda FOR gw_all-erdat,
so_lwati FOR gw_all-wadat_ist,
so_arktx FOR gw_all-arktx,
so_netwr FOR gw_all-netwr,
so_kwmen FOR gw_all-kwmeng,
so_lfimg FOR gw_all-lfimg.
**********************************************************************
* Join über LIKP
**********************************************************************
* Startzeit initialisieren
GET RUN TIME FIELD g_start.
SELECT vbak~auart
vbak~vbeln
vbak~erdat
vbak~kunnr
vbak~vkbur
vbak~vkorg
vbak~vtweg
likp~vbeln
likp~erdat
likp~wadat_ist
vbap~matnr
vbap~arktx
vbap~kwmeng
vbap~netwr
vbap~uepos
lips~lfimg
lips~posnr
vbkd~bzirk
INTO TABLE gt_all
FROM likp
JOIN lips
ON likp~vbeln = lips~vbeln
JOIN vbak
ON vbak~vbeln = lips~vgbel
JOIN vbap
ON vbap~vbeln = lips~vgbel
AND vbap~posnr = lips~vgpos
JOIN vbkd
ON vbkd~vbeln = vbap~vbeln
* AND vbkd~posnr = vbap~posnr
WHERE vbak~vbeln IN so_vbeln
AND vbak~auart IN so_auart
AND vbak~erdat IN so_erdat
AND vbak~kunnr IN so_kunnr
AND vbak~vkbur IN so_vkbur
AND vbak~vkorg IN so_vkorg
AND vbak~vtweg IN so_vtweg
AND vbap~matnr IN so_matnr
AND vbap~uepos IN so_uepos
AND vbkd~bzirk IN so_bzirk
AND likp~vbeln IN so_lbeln
AND likp~erdat IN so_lerda
AND likp~wadat_ist IN so_lwati
AND vbap~arktx IN so_arktx
AND vbap~netwr IN so_netwr
AND vbap~kwmeng IN so_kwmen
AND lips~lfimg IN so_lfimg.
* Ende-Zeit hohlen
GET RUN TIME FIELD g_ende.
* Protokoll ausgeben
g_diff = g_ende - g_start.
g_anz = LINES( gt_all ).
WRITE: / 'JOIN 1'.
WRITE: / 'Anzahl gelesener Sätze:', g_anz.
WRITE: / 'Dauer:', g_diff.
**********************************************************************
* Daten einzeln lesen und erst zum Schlauss zusammen stecken
**********************************************************************
* Neue Startzeit setzten
GET RUN TIME FIELD g_start.
SELECT vbak~vbeln
vbap~posnr
vbak~auart
vbak~erdat
vbak~kunnr
vbak~vkbur
vbak~vkorg
vbak~vtweg
vbap~matnr
vbap~arktx
vbap~kwmeng
vbap~netwr
vbap~uepos
vbkd~bzirk
FROM vbak
JOIN vbap
ON vbap~vbeln = vbak~vbeln
JOIN vbkd
ON vbkd~vbeln = vbap~vbeln
* AND vbkd~posnr = vbap~posnr
INTO TABLE gt_vbak
WHERE vbak~vbeln IN so_vbeln
AND vbak~auart IN so_auart
AND vbak~erdat IN so_erdat
AND vbak~kunnr IN so_kunnr
AND vbak~vkbur IN so_vkbur
AND vbak~vkorg IN so_vkorg
AND vbak~vtweg IN so_vtweg
AND vbap~matnr IN so_matnr
AND vbap~uepos IN so_uepos
AND vbap~arktx IN so_arktx
AND vbap~netwr IN so_netwr
AND vbap~kwmeng IN so_kwmen.
* Tabelle gt_vbak für FOR ALL ENTRIES aufbereiten
SORT gt_vbak BY vbeln.
DELETE ADJACENT DUPLICATES FROM gt_vbak.
IF NOT gt_vbak IS INITIAL.
* Aus der vbfa die Lieferungen zum Auftag lesen
SELECT vbfa~vbeln
FROM vbfa
INTO TABLE gt_vbfa
FOR ALL ENTRIES IN gt_vbak
WHERE vbelv = gt_vbak-vbeln
AND posnv = gt_vbak-posnr
AND vbtyp_n = 'J' "Lieferung
AND vbtyp_v = 'C'. "Auftrag
* Tabelle gt_vbfa für FOR ALL ENTRIES aufbereiten
SORT gt_vbfa BY vbeln posnn.
DELETE ADJACENT DUPLICATES FROM gt_vbfa.
IF NOT gt_vbfa IS INITIAL.
SELECT lips~vgbel
lips~vgpos
likp~vbeln
lips~posnr
likp~erdat
likp~wadat_ist
lips~lfimg
FROM likp
JOIN lips
ON lips~vbeln = likp~vbeln
INTO TABLE gt_likp
FOR ALL ENTRIES IN gt_vbfa
WHERE likp~vbeln = gt_vbfa-vbeln
AND likp~vbeln IN so_lbeln
AND likp~erdat IN so_lerda
AND likp~wadat_ist IN so_lwati
AND lips~lfimg IN so_lfimg.
SORT gt_likp.
ENDIF. "not gt_vbfa is initial.
ENDIF. "not gt_vbak is initial.
CLEAR gt_all.
LOOP AT gt_vbak INTO gw_vbak.
LOOP AT gt_likp INTO gw_likp WHERE vgbel = gw_vbak-vbeln
AND vgpos = gw_vbak-posnr.
gw_all-auart = gw_vbak-auart.
gw_all-vbeln = gw_vbak-vbeln.
gw_all-erdat = gw_vbak-erdat.
gw_all-kunnr = gw_vbak-kunnr.
gw_all-vkbur = gw_vbak-vkbur.
gw_all-vkorg = gw_vbak-vkorg.
gw_all-vtweg = gw_vbak-vtweg.
gw_all-matnr = gw_vbak-matnr.
gw_all-arktx = gw_vbak-arktx.
gw_all-kwmeng = gw_vbak-kwmeng.
gw_all-netwr = gw_vbak-netwr.
gw_all-uepos = gw_vbak-uepos.
gw_all-bzirk = gw_vbak-bzirk.
gw_all-vbeln_li = gw_likp-vbeln.
gw_all-erdat_li = gw_likp-erdat.
gw_all-wadat_ist = gw_likp-wadat_ist.
gw_all-lfimg = gw_likp-lfimg.
gw_all-posnr = gw_likp-posnr.
APPEND gw_all TO gt_all.
ENDLOOP.
ENDLOOP.
GET RUN TIME FIELD g_ende.
g_diff = g_ende - g_start.
g_anz = LINES( gt_all ).
WRITE: /,/ 'FOR ALL ENTRIES'.
WRITE: / 'Anzahl gelesener Sätze:', g_anz.
WRITE: / 'Dauer:', g_diff.