Code: Alles auswählen.
TYPES:
BEGIN OF ty_address_key,
business_partner_id TYPE bu_partner,
address_id TYPE ad_addrnum,
END OF ty_address_key,
tty_address_ids TYPE SORTED TABLE OF ty_address_key WITH UNIQUE KEY business_partner_id.
DATA:
address_ids TYPE tty_address_ids.
Code: Alles auswählen.
SELECT addrnumber, smtp_addr FROM adr6
FOR ALL ENTRIES IN @address_ids
WHERE addrnumber = @address_ids-address_id
INTO @DATA(email_address).
email_addresses = VALUE #( BASE email_addresses
(
address_id = email_address-addrnumber
business_partner_id = address_ids[ address_id = email_address-addrnumber ]-business_partner_id
email_address = email_address-smtp_addr
)
).
ENDSELECT.
Code: Alles auswählen.
SELECT @std_address_ids-business_partner_id, addrnumber, smtp_addr FROM adr6
FOR ALL ENTRIES IN @std_address_ids
WHERE addrnumber = @std_address_ids-address_id
INTO TABLE @DATA(email_address).
Code: Alles auswählen.
SELECT a~partner, b~addrnumber, b~smtp_addr FROM but021_fs AS a
JOIN adr6 AS b ON b~addrnumber = a~addrnumber
FOR ALL ENTRIES IN @std_address_ids
WHERE a~partner = @std_address_ids-business_partner_id
AND b~addrnumber = @std_address_ids-address_id
INTO TABLE @DATA(email_address2).
Code: Alles auswählen.
SELECT addrnumber, smtp_addr FROM adr6
FOR ALL ENTRIES IN @std_address_ids
WHERE addrnumber = @std_address_ids-address_id
INTO TABLE @DATA(email_address).
Folgende Benutzer bedankten sich beim Autor a-dead-trousers für den Beitrag:
tm987456
Jein. Ich würde die Query die die Business Partner IDs und zugehörigen Adressen IDs ermittelt mit der zweiten Query verknüpfen WENN ES SINN macht.
Das Problem ist, dass ein "FOR ALL ENTRIES" die Möglichkeiten des SELECTs einfach arg einschränkt. Allerdings hat uns SAP in modernen Releases ( ab. 7.52 ) eine Alternative gegeben die man manchmal verwenden kann: Man darf neuerdings EINE interne Tabelle in einer JOIN-Bedingungn verwenden anstatt einer DB-Tabelle. -->Doku<--tm987456 hat geschrieben: ↑20.10.2020 13:08Warum kann ich nicht sowas schreiben:Was übersehe ich? Das muss doch leichter/schneller zu lösen sein.Code: Alles auswählen.
SELECT @std_address_ids-business_partner_id, addrnumber, smtp_addr FROM adr6 FOR ALL ENTRIES IN @std_address_ids WHERE addrnumber = @std_address_ids-address_id INTO TABLE @DATA(email_address).
Code: Alles auswählen.
REPORT.
SELECT land1, waers, spras
FROM t005
INTO TABLE @DATA(lt_test) UP TO 5 ROWS.
SELECT itab~land1, itab~waers,
t005t~landx
FROM @lt_test AS itab JOIN t005t ON t005t~land1 = itab~land1
WHERE t005t~spras = @sy-langu
INTO TABLE @DATA(lt_mixed).
BREAK-POINT.
Folgende Benutzer bedankten sich beim Autor black_adept für den Beitrag (Insgesamt 5):
qyurryus • ewx • a-dead-trousers • tm987456 • Radinator
Code: Alles auswählen.
SELECT ids~business_partner_id, ids~address_id, emails~smtp_addr FROM adr6 AS emails
INNER JOIN @std_address_ids AS ids ON ids~address_id = emails~addrnumber
INTO TABLE @email_addresses.
Das kann ich mir, ehrlich gesagt, nicht vorstellen. Was ABAP da macht, kann ja kein echter JOIN auf Datenbankebene sein, denn die Datenbank kennt die interne Tabelle nicht. Also kann ABAP ja nichts anderes machen, als die Werte aus der internen Tabelle einzeln an die Datenbank zu übertragen, vermutlich als WHERE fraglicher_wert IN (wert1,wert2,wert3,...). Genau das macht aber auch der FOR ALL ENTRIES IN. Von daher halte ich es performancetechnisch für ein Nullsummenspiel. Müsste man mal austesten, was da schneller ist.Macht es Sinn prinzipiell FOR ALL ENTIRES Situationen durch den Join zu ersetzten? Performance sollte ja auch besser sein.
äquivalent sein soll zuGelöst habe ich das wie folgt:Code: Alles auswählen.
SELECT addrnumber, smtp_addr FROM adr6 FOR ALL ENTRIES IN @address_ids WHERE addrnumber = @address_ids-address_id INTO @DATA(email_address). email_addresses = VALUE #( BASE email_addresses ( address_id = email_address-addrnumber business_partner_id = address_ids[ address_id = email_address-addrnumber ]-business_partner_id email_address = email_address-smtp_addr ) ). ENDSELECT.
Das kann doch eigentlich gar nicht sein, denn in der zweiten Version liest Du eine ganz andere Datenbanktabelle als in der ersten?! Es sei denn, es gibt zwischen den Inhalten dieser Datenbanktabellen Konsistenzabhängigkeiten, die ich nicht kenne (die Tabelle but021_fs sehe ich zum ersten Mal).So würde es gehen, aber ein eigentlich unnötiger Join.
Code: Alles auswählen.
SELECT a~partner, b~addrnumber, b~smtp_addr FROM but021_fs AS a JOIN adr6 AS b ON b~addrnumber = a~addrnumber FOR ALL ENTRIES IN @std_address_ids WHERE a~partner = @std_address_ids-business_partner_id AND b~addrnumber = @std_address_ids-address_id INTO TABLE @DATA(email_address2).
Code: Alles auswählen.
REPORT ZTEST3.
TYPES: BEGIN OF KOMISCHER_DATENTYP,
ADDRESS_ID TYPE ADR6-ADDRNUMBER,
BUSINESS_PARTNER_ID TYPE BU_PARTNER,
EMAIL_ADDRESS TYPE AD_SMTPADR,
END OF KOMISCHER_DATENTYP,
BEGIN OF EMAIL_ADDRESSES,
ADDRESS_ID TYPE ADR6-ADDRNUMBER,
BUSINESS_PARTNER_ID TYPE BU_PARTNER,
EMAIL_ADDRESS TYPE AD_SMTPADR,
END OF EMAIL_ADDRESSES.
DATA: ADDRESS_IDS TYPE HASHED TABLE OF KOMISCHER_DATENTYP WITH UNIQUE KEY ADDRESS_ID,
EMAIL_ADDRESSES TYPE HASHED TABLE OF EMAIL_ADDRESSES WITH UNIQUE KEY ADDRESS_ID.
SELECT ADDRNUMBER, SMTP_ADDR FROM ADR6
FOR ALL ENTRIES IN @ADDRESS_IDS
WHERE ADDRNUMBER = @ADDRESS_IDS-ADDRESS_ID
INTO TABLE @DATA(TEMP_TABLE).
EMAIL_ADDRESSES = VALUE #( FOR <ZEILE> IN TEMP_TABLE ( ADDRESS_ID = <ZEILE>-ADDRNUMBER
BUSINESS_PARTNER_ID = ADDRESS_IDS[ ADDRESS_ID = <ZEILE>-ADDRNUMBER ]-BUSINESS_PARTNER_ID
EMAIL_ADDRESS = <ZEILE>-SMTP_ADDR ) ).
FREE TEMP_TABLE.
Code: Alles auswählen.
APPEND VALUE #( address_id = email_address-addrnumber
business_partner_id = address_ids[ address_id = email_address-addrnumber ]-business_partner_id
email_address = email_address-smtp_addr )
TO email_addresses.
Code: Alles auswählen.
emailadresse = email_addresses[ address_id = whatever ]-smtp_addr.
Folgende Benutzer bedankten sich beim Autor DeathAndPain für den Beitrag:
tm987456
Code: Alles auswählen.
t2 = VALUE #( BASE t1 ( 4 ) ).
"works as
CLEAR t2.
t2 = t1.
INSERT 4 INTO TABLE t2.
Doch! SELECT-Schleifen holen zeilenweise die Ergebnisse aus der Datenbank. Du hast also pro Zeile eine Kommunikation mit der Datenbank. Ich bin nicht sicher, inwieweit ABAP das mit Pufferungen abschwächt, aber im Prinzip setzt eine SELECT-Schleife einen CURSOR und FETCHt dann Zeile für Zeile die Ergebnisse.Die For-Schleife ist auch eine schöne Lösung. Allerdings ging es mir ja darum eine zusätzliche Schleife zu vermeiden. SELECT, LOOP und FOR nimmt sich da glaube ich nicht so viel.
Was bedeutet, dass der Key für die Schleife in Deiner Ursprungslösung nicht zu gebrauchen war und dort dann also sequentiell wie in einer Standardtabelle gesucht worden ist. Tipp: Für Fälle wie diesen ist es möglich, interne Tabellen mit mehreren Schlüsseln auszustatten.Key ist Partner, da ich das für andere Zugriffe brauche.
Ich wusste zwar nicht, dass er das so gesagt hat, aber es ergibt sich logisch aus der Syntax. Wenn Du eine ZuweisungHorst Keller über value:
https://blogs.sap.com/2014/09/29/abap-n ... pressions/
Code: Alles auswählen.
ergebnistabelle = ...
Code: Alles auswählen.
CLEAR abc.
abc = def(4) && `01`.
Wobei mir Leute lieber sind, die vorsichtshalber ein CLEAR schreiben als solche die es dann mal irgendwo vergessen wo es wichtig ist. Wahrscheinlich ist das einfach im Muskelgedächtnis der Finger verankert.DeathAndPain hat geschrieben: ↑26.10.2020 17:56{rant}Dementsprechend braucht man davor auch keinen CLEAR. Das regt mich immer auf, wenn ich sehe, wie manche Leute aus panischer Angst, mit alten Feldwerten weiterzuarbeiten, ihren Code mit sinnlosen CLEAR-Befehlen zukleistern. Insbesondere ist jeder CLEAR vor einer direkten Zuweisung wie dieser für die Katz (außer wenn die Zielvariable auch auf der rechten Seite der Zuweisung auftaucht, was in Deinem BASE-Fall natürlich der Fall wäre). Für mich hat das auch eine meinungsbildende Bedeutung. Wenn ich:
sehe, dann schließe ich daraus, dass ich Code eines Programmierers vor mir habe, der in blind eingehämmerten Mustern programmiert, anstatt darüber nachzudenken, was er schreibt. Aber ich schweife ab. Du hast Dir in dieser Richtung ja nichts zuschulden kommen lassen. 😊{/rant}Code: Alles auswählen.
CLEAR abc. abc = def(4) && `01`.
Wer legt denn so einen sinnlosen Check an? Habe selten etwas Überflüssigeres gesehen.
Code: Alles auswählen.
t2 = VALUE #( BASE t1 ( 4 ) ).
"works as
CLEAR t2.
t2 = t1.
INSERT 4 INTO TABLE t2.
Ich verstehe Deinen Gedankengang, aber nach meiner Erfahrung geht er in der Praxis nicht auf. An entscheidender Stelle wird dann doch das CLEAR vergessen - oder es werden andere Fehler gemacht, bei denen der kritische Leser klar erkennen kann, dass blind Schablonen angewendet wurden, anstatt sich geistig klar darüber zu werden, was man da programmiert.black_adept hat geschrieben:Wobei mir Leute lieber sind, die vorsichtshalber ein CLEAR schreiben als solche die es dann mal irgendwo vergessen wo es wichtig ist.
Man kann das geistige Dabeisein-bei-dem-was-man-codet nicht durch Dressierte-Affen-Methodik ersetzen, jedenfalls nicht unter Aufrechterhaltung desselben Qualitätsniveaus. Dafür ist Programmieren zu anspruchsvoll.black_adept hat geschrieben:Wahrscheinlich ist das einfach im Muskelgedächtnis der Finger verankert.
Das ist die Frage, ob es die Aufgabe des Compilers ist, schlampigen Code zu optimieren. Die Philosophie in SAP scheint ja doch eine andere zu sein, denn die Erweiterte Programmprüfung und der Code Inspector weisen einen ja auf jeden Furz hin, auch wenn man da teilweise sicherlich auch automatisiert optimieren könnte. Ich finde es aber auch richtig so. Ausgeführt werden sollte, was programmiert wurde.black_adept hat geschrieben:Und ich frage mich gerade wie gut der Compiler von ABAP ist - der könnte solch ein offensichtlich überflüssiges Konstrukt doch intern optimieren.