*---------------------------------------------------------------------*
* Z _ B J H _ I N N E R _ J O I N *
* *
* Autor: Bernd Haase (BJH Software) *
*---------------------------------------------------------------------*
* Einlesemöglichkeiten von externen SAP-Tabellen in interne Tabellen. *
* Zugriffe auf Tabelle, welche über Fremdschlüssel verknüpft sind. *
* Vorstellung unterschiedlicher Methodiken, dessen Einsatz im Fall zu *
* Fall zu entscheiden ist unter den Gesichtspunkten zu erwartende *
* Ergebnismenge, Performance, Komplexittät. *
* *
* 1.) Konventionel: geschachtelte Select-Struktur. *
* 2.) Hashed: Blockweises Lesen der EKKO-Tabelle und mischen *
* 3.) Join: allerdings satzweises Lesen und fortschreiben *
* 4.) Join: auffüllen und einlesen in eine interne Tabelle *
* 5.) Collect: Fremdschlüsselbeziehungen auffüllen *
* 6.) Mega-Join: 7 Tabellen gleichzeitig verknüpft. Nur wenn die Werte*
* in allen Tabellen zugeordnet werden konnten, ist der Datensatz *
* gültig. Initialwerte führen zur Ablehnung des Datensatzes ! *
*---------------------------------------------------------------------*
* 20.07.2004 BHaa: Programm erstellt *
* 28.08.2004 BHaa: erweitert um Hashed und Collect Methodik *
*---------------------------------------------------------------------*
REPORT z_bjh_inner_join .
TABLES:
ekko, "Einkaufsbelegkopf
ekpo, "Einkaufsbelegposition
lfa1, "Lieferantenstamm (allgemeiner Teil)
mara, "Allgemeine Materialdaten
makt, "Materialkurztexte
marc, "Werksdaten zum Material
t005, "Länder
t024d. "Materialdisponenten
DATA:
anzahl(6) TYPE n.
DATA:
**************
* Bestellung *
**************
wa_ekko LIKE ekko,
wa_ekpo LIKE ekpo,
* Struktur und interne Tabelle für den Zugriff auf die Bestellkopfdaten
BEGIN OF wk_ekko,
ebeln LIKE ekko-ebeln,
lifnr LIKE ekko-lifnr,
END OF wk_ekko,
wktab_ekko LIKE HASHED TABLE OF wk_ekko WITH UNIQUE KEY ebeln,
* Struktur und interne Tabelle für den Inner-Join, abgekürzt durch "ij"
BEGIN OF wk_ij,
ebeln LIKE ekko-ebeln,
ebelp LIKE ekpo-ebelp,
lifnr LIKE ekko-lifnr,
matnr LIKE ekpo-matnr,
END OF wk_ij,
wktab_ij LIKE TABLE OF wk_ij.
*************
* Lieferant *
*************
DATA:
BEGIN OF ct_lfa1,
lifnr LIKE lfa1-lifnr,
END OF ct_lfa1,
cttab_lfa1 LIKE TABLE OF ct_lfa1,
BEGIN OF wk_lfa1,
lifnr LIKE lfa1-lifnr,
name1 LIKE lfa1-name1,
land1 LIKE lfa1-land1,
END OF wk_lfa1,
wktab_lfa1 LIKE HASHED TABLE OF wk_lfa1 WITH UNIQUE KEY lifnr.
************
* Material *
************
DATA:
BEGIN OF ct_mara,
matnr LIKE mara-matnr,
END OF ct_mara,
cttab_mara LIKE TABLE OF ct_mara,
BEGIN OF wk_mara,
matnr LIKE mara-matnr,
maktx LIKE makt-maktx, "Kurztext zum Material
END OF wk_mara,
wktab_mara LIKE HASHED TABLE OF wk_mara WITH UNIQUE KEY matnr.
* Struktur und interne Tabelle für den Mega-Inner-Join über 7 Datenbank-
* tabellen
DATA:
BEGIN OF mega_ij,
ebeln LIKE ekko-ebeln, "Bestellnummer
ebelp LIKE ekpo-ebelp, "Bestellposition
lifnr LIKE ekko-lifnr, "Lieferant
intca LIKE t005-intca, "ISO-Code des Landes
matnr LIKE ekpo-matnr, "Material
werks LIKE ekpo-werks, "Werk, in welches geliefert werden soll
dsnam LIKE t024d-dsnam, "Name des Disponenten
maktx LIKE makt-maktx, "Kurztext zum Material
END OF mega_ij,
megatab_ij LIKE TABLE OF mega_ij.
*---------------------------------------------------------------------*
* *
* A u s w a h l b i l d s c h i r m *
* *
*---------------------------------------------------------------------*
SELECT-OPTIONS:
so_lifnr FOR ekko-lifnr, "Lieferantennummer
so_matnr FOR ekpo-matnr. "Materialnummer
INITIALIZATION.
CLEAR: so_lifnr. REFRESH: so_lifnr.
* Vorbesetzung eines Lieferanten, um die Ergebnismenge einzugrenzen
MOVE 'I' TO so_lifnr-sign.
MOVE 'EQ' TO so_lifnr-option.
MOVE '205670' TO so_lifnr-low.
APPEND so_lifnr.
START-OF-SELECTION.
MOVE 0 TO anzahl.
********************
* 1. Konventionell *
********************
* Konventionelle Methodik zum Auslesen von Einkufskopfadten und deren
* Positionen
CLEAR: wktab_ij, anzahl.
SELECT * FROM ekko INTO wa_ekko
WHERE lifnr IN so_lifnr.
SELECT * FROM ekpo INTO wa_ekpo
WHERE ebeln = wa_ekko-ebeln
AND matnr IN so_matnr.
MOVE-CORRESPONDING wa_ekko TO wk_ij.
MOVE-CORRESPONDING wa_ekpo TO wk_ij.
APPEND wk_ij TO wktab_ij.
* WRITE: / wa_ekko-ebeln, wa_ekpo-ebelp, wa_ekko-lifnr,
* wa_ekpo-matnr.
ADD 1 TO anzahl.
ENDSELECT.
ENDSELECT.
* Statistik. Ergebnis anzeigen
IF sy-subrc = 0.
* SKIP 1.
WRITE AT: /1 'Select * into wa', 30 anzahl, 37 'Datensätze'.
ELSE.
WRITE: / 'Keine Daten gefunden.'.
ENDIF.
SKIP 1.
*************
* 2. Hashed *
*************
CLEAR: wktab_ij, anzahl.
* einmaliges EInlesen aller betroffenen Bestellungen
SELECT ebeln lifnr FROM ekko
INTO TABLE wktab_ekko
WHERE lifnr IN so_lifnr.
* einzelweises Nachlesen der Positionen, denen dann aber die Kopfdaten
* beimischen dabei bezieht sich die Auswahlmenge der einzulesenden Daten
* der Positionen jedoch schon auf die Wertemenge (Ergebnistabelle) der
* gefundenen Kopfdaten
SELECT * FROM ekpo INTO wa_ekpo
FOR ALL ENTRIES IN wktab_ekko
WHERE ebeln = wktab_ekko-ebeln
AND matnr IN so_matnr.
* Positionsatz. Nun prüfen, ob es zu diesem auch einen Kopfsatz gibt.
* Die Auswahlmenge wurde bereits beim Einlesen reduziert
READ TABLE wktab_ekko INTO wk_ekko
WITH TABLE KEY ebeln = wa_ekpo-ebeln.
IF sy-subrc = 0.
MOVE-CORRESPONDING wa_ekko TO wk_ij.
MOVE-CORRESPONDING wa_ekpo TO wk_ij.
APPEND wk_ij TO wktab_ij.
* WRITE: / wa_ekko-ebeln, wa_ekpo-ebelp, wa_ekko-lifnr,
* wa_ekpo-matnr.
ADD 1 TO anzahl.
ENDIF.
ENDSELECT.
* Statistik. Ergebnis anzeigen
IF sy-subrc = 0.
* SKIP 1.
WRITE AT: /1 'Select und Hashed', 30 anzahl, 37 'Datensätze'.
ELSE.
WRITE: / 'Keine Daten gefunden.'.
ENDIF.
SKIP 1.
***************************
* 3. Inner Join satzweise *
***************************
* Inner-Join-Methodik mit satzweisem Einlesen
MOVE 0 TO anzahl.
SELECT ij_ekko~ebeln ij_ekpo~ebelp ij_ekko~lifnr ij_ekpo~matnr
FROM ekko AS ij_ekko
INNER JOIN ekpo AS ij_ekpo
ON ij_ekko~ebeln = ij_ekpo~ebeln
INTO (wa_ekko-ebeln, wa_ekpo-ebelp, wa_ekko-lifnr, wa_ekpo-matnr)
WHERE ij_ekko~lifnr IN so_lifnr
AND ij_ekpo~matnr IN so_matnr.
* WRITE: / wa_ekko-ebeln, wa_ekpo-ebelp, wa_ekko-lifnr,
* wa_ekpo-matnr.
ADD 1 TO anzahl.
ENDSELECT.
IF sy-subrc = 0.
* SKIP 1.
WRITE AT: /1 'Inner Join into wa', 30 anzahl, 37 'Datensätze'.
ELSE.
WRITE: / 'Keine Daten gefunden.'.
ENDIF.
*******************************
* 4. Inner Join tabellenweise *
*******************************
* Inner-Join-Methodik mit tabellenweisem Einlesen
SELECT *
FROM ekko AS ij_ekko
INNER JOIN ekpo AS ij_ekpo
ON ij_ekko~ebeln = ij_ekpo~ebeln
INTO CORRESPONDING FIELDS OF TABLE wktab_ij
WHERE ij_ekko~lifnr IN so_lifnr
AND ij_ekpo~matnr IN so_matnr.
DESCRIBE TABLE wktab_ij LINES anzahl.
SKIP 1.
WRITE AT: /1 'Inner Join into Table', 30 anzahl, 37 'Datensätze'.
**************
* 5. Collect *
**************
* eignet sich, wenn von einer Tabelle zusätzliche Daten aus weiteren
* Tabellen eingelesen werden sollen, welche von den Ursprungsdaten über
* Fremdschlüsselbeziehungen erreichbar sind.
* Die Collect-Methodik ist eigentlich zum Aufaddieren für Gruppensummen
* entwickelt worden, eignet sich aber für die Fremdschlüsselbeziehungen
CLEAR: megatab_ij, cttab_lfa1, cttab_mara, wktab_lfa1, wktab_mara,
anzahl.
* Ausgangstabelle ist die bereits unter Punkt 4. erzeugte Ergebnismenge
LOOP AT wktab_ij INTO wk_ij.
MOVE wk_ij-lifnr TO ct_lfa1-lifnr.
COLLECT ct_lfa1 INTO cttab_lfa1.
MOVE wk_ij-matnr TO ct_mara-matnr.
COLLECT ct_mara INTO cttab_mara.
ENDLOOP.
* lieber mit Abfrage, denn bei leere Ergebnismenge kann das System davon
* ausgehen, alle Werte der gewünschten Tabelle einzulesen
IF NOT cttab_lfa1 IS INITIAL.
SELECT * FROM lfa1
INTO CORRESPONDING FIELDS OF TABLE wktab_lfa1
FOR ALL ENTRIES IN cttab_lfa1
WHERE lifnr = cttab_lfa1-lifnr.
ENDIF.
IF NOT cttab_mara IS INITIAL.
* Inner-Join-Methodik zum Einelsen der Materialen und deren Texte
SELECT *
FROM mara AS ij_mara
INNER JOIN makt AS ij_makt
ON ij_mara~matnr = ij_makt~matnr
INTO CORRESPONDING FIELDS OF TABLE wktab_mara
FOR ALL ENTRIES IN cttab_mara
WHERE ij_mara~matnr = cttab_mara-matnr
AND ij_makt~spras = sy-langu.
ENDIF.
* erneuter Lauf der Ausgangstabelle, da jetzt aber alle zusätzlich
* benötigten Daten zur Verfügung stehen, kann gemischt werden und die
* Endergebnistabelle befüllt werden. Sollten für die Fremdschlüssel-
* beziehung keine zusätzlichen Daten existieren, so werden diese Felder
* frei gelassen. Reihenfolge beachten !
LOOP AT wktab_ij INTO wk_ij.
READ TABLE wktab_lfa1 INTO wk_lfa1
WITH TABLE KEY lifnr = wk_ij-lifnr.
IF sy-subrc <> 0.
CLEAR: wk_lfa1.
ENDIF.
READ TABLE wktab_mara INTO wk_mara
WITH TABLE KEY matnr = wk_ij-matnr.
IF sy-subrc <> 0.
CLEAR: wk_mara.
ENDIF.
MOVE-CORRESPONDING wk_lfa1 TO mega_ij.
MOVE-CORRESPONDING wk_mara TO mega_ij.
MOVE-CORRESPONDING wk_ij TO mega_ij.
APPEND mega_ij TO megatab_ij.
ENDLOOP.
DESCRIBE TABLE megatab_ij LINES anzahl.
SKIP 1.
WRITE AT: /1 'Collect Methodik', 30 anzahl, 37 'Datensätze'.
****************
* 6. Mega-Join *
****************
* auch so könnte man die Punkte 4. und 5. realisieren. Die Wertemenge
* ist aber eingeschränkt, da keine Outer-Join Methodik
* Mega-Join über 7 Tabellen. Dauert ein wenig, bevor das Ergebnis fest-
* steht. Allerdings ist Nachteil, das sollte die Materialnummer fehlen
* (Nichtlagersätze, Dienstleistungen), der gesamte Datensatz ignoriert
* wird, da kein erfolgreicher Zugriff auf die Materialtabelle durchge-
* führt werden konnte. Sollten Felder mit gleichem Namen in mehreren
* Tabellen vorkommen, Übertrag und Füllung interne Tabelle mega_ij
* beachten (Beispiel WERKS exisitert in den Tabellen EKPO; LFA1, MARC
* und T024D).
SELECT *
FROM ekko AS ij_ekko
INNER JOIN ekpo AS ij_ekpo
ON ij_ekko~ebeln = ij_ekpo~ebeln
INNER JOIN lfa1 AS ij_lfa1
ON ij_ekko~lifnr = ij_lfa1~lifnr
INNER JOIN marc AS ij_marc
ON ij_ekpo~matnr = ij_marc~matnr
AND ij_ekpo~werks = ij_marc~werks
INNER JOIN makt AS ij_makt
ON ij_ekpo~matnr = ij_makt~matnr
INNER JOIN t005 AS ij_t005
ON ij_lfa1~land1 = ij_t005~land1
INNER JOIN t024d AS ij_t024d
ON ij_ekpo~werks = ij_t024d~werks
AND ij_marc~dispo = ij_t024d~dispo
INTO CORRESPONDING FIELDS OF TABLE megatab_ij
WHERE ij_ekko~lifnr IN so_lifnr
AND ij_ekpo~matnr IN so_matnr
AND ij_makt~spras = sy-langu.
DESCRIBE TABLE megatab_ij LINES anzahl.
SKIP 1.
WRITE AT: /1 'Mega Join into Table', 30 anzahl, 37 'Datensätze'.
* Ergebnisanzeige für den Mega-Join, jede gefundene Zeile
LOOP AT megatab_ij INTO mega_ij.
WRITE: / mega_ij-ebeln, mega_ij-ebelp,
mega_ij-lifnr, mega_ij-intca,
mega_ij-matnr, mega_ij-werks,
mega_ij-maktx(15), mega_ij-dsnam.
ENDLOOP.
END-OF-SELECTION.
EXIT.
***** Ende *****
* Copyright BJH Software, Datei überarbeitet am: 21.5.2005