Code: Alles auswählen.
REPORT.
CLASS lcl DEFINITION FINAL.
PUBLIC SECTION.
TYPES: BEGIN OF lts_from_to,
from TYPE i,
to TYPE i,
END OF lts_from_to,
ltt_from_to TYPE STANDARD TABLE OF lts_from_to WITH NON-UNIQUE DEFAULT KEY.
CLASS-METHODS:
magic IMPORTING it_zahlen TYPE integer_tab
RETURNING value(rt_data_from_to) TYPE ltt_from_to.
ENDCLASS. "lcl DEFINITION
CLASS lcl IMPLEMENTATION.
METHOD magic.
* Hier bitte tolles Coding einfügen
ENDMETHOD. "magic
ENDCLASS. "lcl IMPLEMENTATION
END-OF-SELECTION.
DATA: gt_zahlen TYPE integer_tab,
gt_from_to TYPE lcl=>ltt_from_to.
APPEND 17 TO gt_zahlen.
APPEND 23 TO gt_zahlen.
APPEND 18 TO gt_zahlen.
APPEND 21 TO gt_zahlen.
APPEND 1111111 TO gt_zahlen.
APPEND -23 TO gt_zahlen.
APPEND 19 TO gt_zahlen.
APPEND -22 TO gt_zahlen.
APPEND -21 TO gt_zahlen.
gt_from_to = lcl=>magic( gt_zahlen ).
Code: Alles auswählen.
von bis
21 21
-23 -21
17 19
23 23
1111111 1111111
Code: Alles auswählen.
METHOD magic.
DATA:
lt_local TYPE integer_tab.
FIELD-SYMBOLS:
<ls_from_to> TYPE lts_from_to.
CLEAR rt_data_from_to.
lt_local = it_zahlen. "Lokale Kopie für Sortierung
DELETE ADJACENT DUPLICATES FROM lt_local.
SORT lt_local.
LOOP AT lt_local ASSIGNING FIELD-SYMBOL(<ld_local>).
IF ( <ls_from_to> IS NOT ASSIGNED )
OR ( <ls_from_to>-to + 1 ) NE <ld_local>.
APPEND INITIAL LINE TO rt_data_from_to ASSIGNING <ls_from_to>.
<ls_from_to>-from = <ld_local>.
ENDIF.
<ls_from_to>-to = <ld_local>.
DELETE lt_local.
ENDLOOP.
ENDMETHOD.
Code: Alles auswählen.
METHOD magic.
FIELD-SYMBOLS:
<ls_from_to> TYPE lts_from_to.
CLEAR rt_data_from_to.
LOOP AT it_zahlen ASSIGNING FIELD-SYMBOL(<ld_local>)
GROUP BY ( number = <ld_local> ) ASCENDING
ASSIGNING FIELD-SYMBOL(<ld_group>).
IF ( <ls_from_to> IS NOT ASSIGNED )
OR ( <ls_from_to>-to + 1 ) NE <ld_group>-number.
APPEND INITIAL LINE TO rt_data_from_to ASSIGNING <ls_from_to>.
<ls_from_to>-from = <ld_group>-number.
ENDIF.
<ls_from_to>-to = <ld_group>-number.
ENDLOOP.
ENDMETHOD.
Folgende Benutzer bedankten sich beim Autor a-dead-trousers für den Beitrag:
DeathAndPain
Code: Alles auswählen.
* Not that great coding. Just meeting the requirement.
DATA:
lt_local TYPE integer_tab,
ls_from_to TYPE lts_from_to.
FREE rt_data_from_to[].
lt_local = it_zahlen. "Lokale Kopie für Sortierung
SORT lt_local.
LOOP AT lt_local INTO DATA(ls_local).
* As per data pattern, even numbers are skipped
* Also, data in TO field is not equal to any FROM field data
IF ( ( ls_local MOD 2 ) EQ 0 ) OR ( ls_from_to-to EQ ls_local ).
CONTINUE.
ELSE.
* Blindly assign the FROM and TO from loop
ls_from_to-from = ls_from_to-to = ls_local.
* Read the 3rd row from here (found after sorting)
READ TABLE lt_local INTO DATA(ls_local_plus_2) INDEX ( sy-tabix + 2 ).
* As per pattern, if the third row entry is equal to (current + 2)
IF sy-subrc EQ 0 AND ( ( ( ls_local + 2 ) EQ ls_local_plus_2 ) ).
* Assign that 3rd row entry to TO
ls_from_to-to = ls_local_plus_2.
* Append the exporting table
APPEND ls_from_to TO rt_data_from_to.
ELSE. " If the +2 Pattern does not match
* Just keep FROM and TO same
* Append the exporting table
APPEND ls_from_to TO rt_data_from_to.
ENDIF.
ENDIF.
ENDLOOP.
Code: Alles auswählen.
method magic.
data: l_waft type lts_from_to.
data: l_next type lts_from_to.
loop at it_zahlen into l_waft-from.
append l_waft to rt_data_from_to.
endloop.
sort rt_data_from_to by from.
loop at rt_data_from_to into l_waft where to is initial.
delete rt_data_from_to.
l_waft-to = l_waft-from.
loop at rt_data_from_to into l_next where to is initial.
if l_next-from ne ( l_waft-to + 1 ).
append l_waft to rt_data_from_to.
exit.
endif.
l_waft-to = l_next-from.
delete rt_data_from_to.
endloop.
if sy-subrc ne 0.
append l_waft to rt_data_from_to.
endif.
endloop.
endmethod.
Zuerst bildet der Befehl die Gruppen anhand des Schlüssels ab. Das sollte aufgrund interner Optimierungen relativ zügig passieren. Erst in der zweiten Phase werden die Befehle die zwischen LOOP und ENDLOOP stehen für die gefundenen Gruppen ausgeführt. Das normale LOOP würde gleich mit der Ausführung loslegen.Dele hat geschrieben:@a-dead-trousers
LOOP AT .... GROUP BY ist ja recht neu. Habe ich noch nicht gekannt.
In der Doku schreiben sie von zwei Phasen. Da frage ich mich, wie performant das ist. Hast du dazu weitere Information?
Code: Alles auswählen.
METHOD magic.
DATA: sytabix TYPE sy-tabix,
zahlen_tab TYPE STANDARD TABLE OF i,
von TYPE i.
FIELD-SYMBOLS: <fs> TYPE i.
zahlen_tab = it_zahlen.
SORT zahlen_tab ASCENDING.
READ TABLE zahlen_tab ASSIGNING <fs> INDEX 1.
von = <fs>.
LOOP AT zahlen_tab ASSIGNING <fs>.
sytabix = sy-tabix.
READ TABLE zahlen_tab TRANSPORTING NO FIELDS WITH KEY table_line = ( <fs> + 1 ).
IF sy-subrc <> 0.
APPEND VALUE lts_from_to( from = von to = <fs> ) TO rt_data_from_to.
READ TABLE zahlen_tab INTO von INDEX sytabix + 1.
IF sy-subrc <> 0.
BREAK-POINT.
* fertig.
return.
ENDIF.
CONTINUE.
ENDIF.
ENDLOOP.
ENDMETHOD.
Folgende Benutzer bedankten sich beim Autor a-dead-trousers für den Beitrag (Insgesamt 2):
black_adept • Thomas R.
Das hätte ich auch erwartet. Ein technisches Problem, dass eine Abstraktionsebene näher an der Hardware gelöst wird, sollte immer effizienter laufen als eine Ebene höher. Deswegen ist in aller Regel auch ein SELECT mit vielen JOINs effizienter, als wenn man viele einzelne SELECTs in Hilfsfelder macht und den JOIN-Abgleich dann per ABAP durchführt, denn mit den JOINs übergibt man der Datenbank die vollständige Information, welche Daten man in Wahrheit sucht, so dass die dann ihre internen Optimierer anwerfen kann.Noch etwas zur Laufzeit bei LOOP AT ... GROUP BY:
Laut der Aussage unseres Schulungsleiters bei der Delta-Schulung ist der GROUP BY Zusatz intern so gut optimiert, dass man trotzdem schneller als mit einer Hilfsvariable für die Erkennung der Gruppenstufen ist.
Jein.DeathAndPain hat geschrieben:Deswegen ist in aller Regel auch ein SELECT mit vielen JOINs effizienter, als wenn man viele einzelne SELECTs in Hilfsfelder macht und den JOIN-Abgleich dann per ABAP durchführt, denn mit den JOINs übergibt man der Datenbank die vollständige Information, welche Daten man in Wahrheit sucht, so dass die dann ihre internen Optimierer anwerfen kann.
Folgende Benutzer bedankten sich beim Autor a-dead-trousers für den Beitrag (Insgesamt 3):
DeathAndPain • black_adept • Thomas R.