Das mag bei kleinen Tabellen in Ordnung sein. Bei großen Datenmengen ist ein LOOP mit CHECK im LOOP denkbar ungünstig.black_adept hat geschrieben:Hi RIG,
in einem soooooo einfachen Fall kannst du dann natürlich auch 1 Form für beides nehmen: Ich gebe dir aber nur ein Outline - du sollst schon selber noch ein wenig rumfrickeln. Das bringt dir letztlich mehr.
1.) Übergabe der Tabelle (generisch) und des Suchwertes ( am besten Typisiert ).
2.) Loop ... Assigning in ein generisches Feldsymbol ( das dann zur Laufzeit deiner Tabellenzeile entspricht ).
3.) Innerhalb des Loop machst du ein MOVE-CORRESPONDING in eine typisierte Struktur, die mindestens das Feld enthält, welches du auswerten möchtest.
4.) Test der typisierten Struktur ob der Suchwert erfüllt ist. Falls ja: zählen
RIG hat geschrieben:Genau da steh ich ja wieder vor meinem Problem mit dem Feldsymbol in meiner Form. Wenn es erst zur Laufzeit zugewiesen werden soll und ich es nicht übergeben darf hab ich noch keinen geschmeidigen Einfall.
Gemeint ist, dass du innerhalb deiner Form-Routine eine Struktur anlegst die, die Felder aus BEIDEN Tabellen beinhaltet und für die Abfrage notwendig sind.black_adept hat geschrieben:Definier das FS vom Type ANY. Dann bekommt es automatisch beim LOOP AT...ASSIGNING den korrekten Type zugewiesen.
Code: Alles auswählen.
Sort gt_cars_bookrent by rentclass.
Sort gt_sched_bookrent by rentclass.
gv_class_want = 'KOMPAKTKLASSE'.
Perform CountGroupLinesTEST Using gt_cars_bookrent
gv_class_want
Changing gv_Lange.
gv_Lange = 0.
Perform CountGroupLinesTEST Using gt_sched_bookrent
gv_class_want
Changing gv_Lange.
form COUNTGROUPLINESTEST using ut_grouped_Table type any table
uv_class_want type zrig_rentclass
changing cv_lange type i.
Data: ls_rentclass type ts_rentclass.
FIELD-SYMBOLS: <ls_FIELDSYMBOL> type any.
LOOP AT ut_grouped_Table ASSIGNING <ls_FIELDSYMBOL>.
MOVE-CORRESPONDING <ls_FIELDSYMBOL> to ls_rentclass.
IF ls_rentclass-rentclass = uv_class_want.
cv_lange = cv_lange + 1.
ENDIF.
IF ls_rentclass-rentclass <> uv_class_want AND cv_Lange > 0.
Exit.
ENDIF.
ENDLOOP.
endform. " COUNTGROUPLINESTEST
Das Makro sieht auch schick aus, da ich aber in mehreren Forms und includes auf die Funktion zugreifen möchte und das dann wiederrum seine Tücken hat habe ich mich für die Variante mit forms und fs entschieden.ewx hat geschrieben:ja, z.B. so:
Alternative wäre ein Makro:Aufruf der Makros:Code: Alles auswählen.
define count_entries. loop at &1 transporting no fields where &2 = &3. add 1 to &4. endloop. end-of-definition.
& ist das "kaufm. UND"...!Code: Alles auswählen.
count_entries gt_cars aa '2' count1. count_entries gt_sched aa '2' count2.
ewx hat geschrieben:Das mag bei kleinen Tabellen in Ordnung sein. Bei großen Datenmengen ist ein LOOP mit CHECK im LOOP denkbar ungünstig.black_adept hat geschrieben:Hi RIG,
in einem soooooo einfachen Fall kannst du dann natürlich auch 1 Form für beides nehmen: Ich gebe dir aber nur ein Outline - du sollst schon selber noch ein wenig rumfrickeln. Das bringt dir letztlich mehr.
1.) Übergabe der Tabelle (generisch) und des Suchwertes ( am besten Typisiert ).
2.) Loop ... Assigning in ein generisches Feldsymbol ( das dann zur Laufzeit deiner Tabellenzeile entspricht ).
3.) Innerhalb des Loop machst du ein MOVE-CORRESPONDING in eine typisierte Struktur, die mindestens das Feld enthält, welches du auswerten möchtest.
4.) Test der typisierten Struktur ob der Suchwert erfüllt ist. Falls ja: zählen
Da fand ich meine Idee besser...!
Wäre mal auszutesten.RIG hat geschrieben:Meine Tabellen sind nicht so groß. Aber für den Fall das sie groß wären, welche Deiner Methoden ist denn dann besser - Makro oder Variante 1?
Hi ewx,ewx hat geschrieben: Das mag bei kleinen Tabellen in Ordnung sein. Bei großen Datenmengen ist ein LOOP mit CHECK im LOOP denkbar ungünstig.
Hallo RIG,RIG hat geschrieben:Code: Alles auswählen.
... IF ls_rentclass-rentclass <> uv_class_want AND cv_Lange > 0. Exit. ENDIF. ...
Kannst Du mir auch sagen warum? Für den Fall das jemand eine unsortierte Tabelle reinschiebt?black_adept hat geschrieben:Hallo RIG,RIG hat geschrieben:Code: Alles auswählen.
... IF ls_rentclass-rentclass <> uv_class_want AND cv_Lange > 0. Exit. ENDIF. ...
ich finde deine Abbruchbedingung recht einfallsreich.
Aber aus demselben Grund aus dem ich ewx schon gerade gefragt habe warum er den LOOP+CHECK suboptimal findet, würde ich dir dazu raten die beiden SORT-Befehle und diese Abbruchbedingung wegzulassen.
Code: Alles auswählen.
IF ls_rentclass-rentclass > uv_class_want.
Exit.
ENDIF.
Genau, weil bei einem Loop über eine Tabelle mit hundert Tausenden von Einträgen jeden Eintrag durchläuft und ein Assign und ein Check macht. Da ist doch ein READ schneller, oder nicht?black_adept hat geschrieben:Hi ewx,ewx hat geschrieben: Das mag bei kleinen Tabellen in Ordnung sein. Bei großen Datenmengen ist ein LOOP mit CHECK im LOOP denkbar ungünstig.
irgendwie kann ich das nicht glauben. Könntest du mal erläutern warum das so sein soll?
Das inperformanteste bei "meiner" Methode ist das MOVE-CORRESPONDING innerhalb des LOOP. Aber selbst das könnte man durch performantere - aber m.E. schlechter lesbarere - Methodik austauschen. Und deine Kritik ist ja auch nicht an diesem Befehl aufgehängt sondern an dem LOOP + CHECK.
Code: Alles auswählen.
Durchlauf Sätze "LOOP" "READ"
1 13.680 40.833 27.835
2 27.360 82.722 40.287
3 41.040 120.952 60.993
4 54.720 159.002 82.381
5 68.400 195.908 108.358
6 82.080 256.552 130.982
7 95.760 268.023 145.924
8 109.440 343.610 170.576
9 123.120 329.162 199.473
10 136.800 367.587 208.661
11 150.480 400.678 249.956
12 164.160 445.614 274.626
13 177.840 469.790 277.409
14 191.520 535.171 312.353
15 205.200 599.543 346.641
16 218.880 615.087 356.632
17 232.560 644.617 383.314
18 246.240 743.851 400.060
19 259.920 674.811 482.823
20 273.600 706.703 380.553
21 287.280 733.762 490.509
22 300.960 787.191 278.219
23 314.640 816.793 276.794
24 328.320 763.948 351.221
25 342.000 880.663 410.866
Code: Alles auswählen.
DATA gt_mara TYPE STANDARD TABLE OF mara WITH NON-UNIQUE DEFAULT KEY.
DATA gt_mara1 TYPE STANDARD TABLE OF mara WITH NON-UNIQUE DEFAULT KEY.
FIELD-SYMBOLS <mara> TYPE ANY.
FIELD-SYMBOLS <value> TYPE ANY.
DATA start TYPE i.
DATA stopp TYPE i.
DATA diff TYPE i.
DATA index TYPE i.
PARAMETERS p_ernam TYPE ernam DEFAULT 'ENNO'.
PARAMETERS p_var TYPE n LENGTH 1 DEFAULT '1'.
PARAMETERS p_anz type i DEFAULT 25.
START-OF-SELECTION.
SELECT * FROM mara INTO TABLE gt_mara1.
WRITE: 'VARIANTE', p_var.
ULINE.
DO p_anz TIMES.
WRITE: / 'Druchlauf:', sy-index.
APPEND LINES OF gt_mara1 TO gt_mara.
sy-dbcnt = LINES( gt_mara ).
WRITE: sy-dbcnt.
CLEAR sy-dbcnt.
GET RUN TIME FIELD start.
CASE p_var.
WHEN '1'.
LOOP AT gt_mara ASSIGNING <mara>.
ASSIGN COMPONENT 'ERNAM' OF STRUCTURE <mara> TO <value>.
CHECK <value> = p_ernam.
ADD 1 TO sy-dbcnt.
ENDLOOP.
WHEN '2'.
SORT gt_mara BY ernam.
READ TABLE gt_mara ASSIGNING <mara> WITH KEY ('ERNAM') = p_ernam BINARY SEARCH.
IF sy-subrc = 0.
ADD 1 TO sy-dbcnt.
index = sy-tabix + 1.
DO.
READ TABLE gt_mara ASSIGNING <mara> INDEX index.
ASSIGN COMPONENT 'ERNAM' OF STRUCTURE <mara> TO <value>.
IF <value> = p_ernam.
ADD 1 TO sy-dbcnt.
ADD 1 TO index.
ELSE.
EXIT. "from do.
ENDIF.
ENDDO.
ENDIF.
ENDCASE.
GET RUN TIME FIELD stopp.
diff = stopp - start.
WRITE: diff.
ENDDO.
*räusper* - die rot markierten Zeilen machen mich doch arg stutzig ob der Aussagekraft dieser Auswertung.ewx hat geschrieben: Durchlauf Sätze "LOOP" "READ"
19 259.920 674.811 482.823
20 273.600 706.703 380.553
21 287.280 733.762 490.509
22 300.960 787.191 278.219
23 314.640 816.793 276.794
24 328.320 763.948 351.221
25 342.000 880.663 410.866
Kommt dann darauf an, ob man das Programm öfter ausführt, als man es liest, oder umgekehrt...black_adept hat geschrieben:Was zeigt uns das? Am Besten ist es einfach auszuprobieren was schneller ist, wie groß der Zeitgewinn ist und ob das den Lesbarkeitsverlust ausgleicht. ( 5 Zeilen Coding vs. 16 Zeilen )