lunes, 14 de enero de 2008

Busquedas en LOOPS anidados

En ocasiones tendremos tablas internas muy pesadas, y deberemos recorrer una dentro de otra para hacer cualquier modificación. En este ejemplo, que hecho con una carga de datos razonable, selecciono las facturas de un mes en it_tab1, luego las de un día en it_tab2, y recorro it_tab2 dentro de it_tab1.

Suponiendo que en it_tab1 haya m entradas y en it_tab2 haya n, si lo hacemos sin más el número de vueltas sería m x n. Incluso, aunque hayamos puesto la cláusula WHERE.

En estos casos, donde además ambas tablas tengan los mismos campos clave, recomiendo usar un índice interno para empezar la búsqueda en la segunda tabla, de esta forma se reducirá el número de vueltas.

En el PERFORM EXCLUIR se puede ver cómo se ha hecho. El resto es paja necesaria.

*&---------------------------------------------------------------------*
*& Report ZINDICES
*&
*&---------------------------------------------------------------------*
*&
*& Un loop dentro de otro loop, con índices
*&---------------------------------------------------------------------*

REPORT zindices.


*&---------------------------------------------------------------------*
*& TOP
*& declaración de tablas, tipos, variables, indices, tablas internas.
*&---------------------------------------------------------------------*
TABLES:
vbrk,
vbrp.

RANGES: rg_fecha FOR vbrk-fkdat.


TYPES: BEGIN OF ty_tab,
"campos de vbrk
vbeln LIKE vbrk-vbeln,
vtweg LIKE vbrk-vtweg,
spart LIKE vbrk-spart,
erdat LIKE vbrk-erdat,
fkdat LIKE vbrk-fkdat,
"Campos de vbrp
posnr LIKE vbrp-posnr,
matnr LIKE vbrp-matnr,
fkimg LIKE vbrp-fkimg,
END OF ty_tab.

DATA:
it_tab1 TYPE TABLE OF ty_tab,
it_tab2 TYPE TABLE OF ty_tab,
it_tab3 TYPE TABLE OF ty_tab,
indice LIKE sy-tabix,
vbeln1 LIKE vbrk-vbeln,
vbeln2 LIKE vbrk-vbeln,
posnr1 LIKE vbrp-posnr,
posnr2 LIKE vbrp-posnr.

************************************************************************

*&---------------------------------------------------------------------*
*& SEL
*& Pantalla de selección
*& Elementos de texto:
*& text-001: "Opciones de selección"
*& text-002: "Opciones del índice"
*& p_anno --> año a elegir
*& p_mes --> mes a elegir
*& p_dia --> día a excluir
*&---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK bl1 WITH FRAME TITLE text-001.

PARAMETERS:
p_anno(4) TYPE n obligatory,
p_mes(2) TYPE n obligatory,
p_dia(2) TYPE n obligatory.
SELECTION-SCREEN END OF BLOCK bl1.

SELECTION-SCREEN BEGIN OF BLOCK bl2 WITH FRAME TITLE text-002.
PARAMETERS:
p_vkorg LIKE vbrk-vkorg,
p_vtweg LIKE vbrk-vtweg.
SELECTION-SCREEN END OF BLOCK bl2.

************************************************************************



*&---------------------------------------------------------------------*
*& EVE
*& Eventos
*&---------------------------------------------------------------------*

START-OF-SELECTION.

PERFORM seleccion_t1 TABLES it_tab1. "Selección de vbrk-vbrp en it_tab1
PERFORM seleccion_t2 TABLES it_tab2. "Selección de vbrk-vbrp en it_tab2

PERFORM excluir
TABLES it_tab1 it_tab2 it_tab3. "it_tab3 = it_tab2 - it_tab1.

************************************************************************
*&---------------------------------------------------------------------*
*& F01
*& Subrutinas
*&---------------------------------------------------------------------*

*&---------------------------------------------------------------------*
*& Form seleccion_t1
*&---------------------------------------------------------------------*
* Selecciona las facturas y posiciones del año y mes elegido
*----------------------------------------------------------------------*
* -->P_TAB1 it_tab1
*----------------------------------------------------------------------*

FORM seleccion_t1 TABLES p_tab1 LIKE it_tab1.

DATA: lv_fecha_low LIKE sy-datum,
lv_fecha_high LIKE sy-datum.

CONCATENATE p_anno p_mes '01' INTO lv_fecha_low.
PERFORM buscar_ultimo_dia USING lv_fecha_low
CHANGING lv_fecha_high.

CLEAR rg_fecha.
MOVE 'I' TO rg_fecha-sign.
MOVE 'BT' TO rg_fecha-option.
MOVE lv_fecha_high TO rg_fecha-high.
MOVE lv_fecha_low TO rg_fecha-low.
APPEND rg_fecha. CLEAR rg_fecha.

READ TABLE rg_fecha INDEX 1.

SELECT
a~vbeln a~vtweg a~spart a~erdat a~fkdat
b~posnr b~matnr b~fkimg
INTO CORRESPONDING FIELDS OF TABLE p_tab1
FROM vbrk AS a
INNER JOIN vbrp AS b ON a~vbeln = b~vbeln
WHERE a~fkdat IN rg_fecha
AND a~vkorg = p_vkorg
AND a~vtweg = p_vtweg.


ENDFORM. " seleccion_t1
*&---------------------------------------------------------------------*
*& Form seleccion_t2
*&---------------------------------------------------------------------*
* Selecciona las facturas del día elegido
*----------------------------------------------------------------------*
* -->P_TAB2 it_tab2
*----------------------------------------------------------------------*
FORM seleccion_t2 TABLES p_tab2 LIKE it_tab2.

DATA: lv_fecha LIKE vbrk-fkdat.

CONCATENATE p_anno p_mes p_dia INTO lv_fecha.

SELECT
a~vbeln a~vtweg a~spart a~erdat a~fkdat
b~posnr b~matnr b~fkimg
INTO CORRESPONDING FIELDS OF TABLE p_tab2
FROM vbrk AS a
INNER JOIN vbrp AS b ON a~vbeln = b~vbeln
WHERE a~fkdat = lv_fecha
AND a~vkorg = p_vkorg
AND a~vtweg = p_vtweg.


ENDFORM. " seleccion_t2
*&---------------------------------------------------------------------*
*& Form excluir
*&---------------------------------------------------------------------*
* hacer que p_tab3 = p_tab1 - p_tab2
*----------------------------------------------------------------------*
* -->P_TAB1 it_tab1
* -->P_TAB2 it_tab2
* -->P_TAB3 it_tab3
*----------------------------------------------------------------------*
FORM excluir TABLES p_tab1 LIKE it_tab1
p_tab2 LIKE it_tab2
p_tab3 LIKE it_tab3.

*Ahora, tengo que eliminar de t_no_asis los pedidos y posiciones que ESTÉN en t_handling

*Ordeno las tablas
SORT p_tab1 BY vbeln posnr.
SORT p_tab2 BY vbeln posnr.

*Ahora, busco
CLEAR indice. ADD 1 TO indice.
LOOP AT p_tab1.
vbeln1 = p_tab1-vbeln.
posnr1 = p_tab1-posnr.
LOOP AT p_tab2 FROM indice.
ADD 1 TO indice.
vbeln2 = p_tab2-vbeln.
posnr2 = p_tab2-posnr.
IF vbeln2 > vbeln1 OR
( vbeln2 EQ vbeln1 AND posnr2 > posnr1 ).
EXIT.
ELSE.
IF vbeln2 EQ vbeln1 AND posnr2 EQ posnr1.
MOVE-CORRESPONDING p_tab1 TO p_tab3.
MOVE-CORRESPONDING p_tab2 TO p_tab3.
APPEND p_tab3. CLEAR p_tab3.
ENDIF.
ENDIF.
ENDLOOP.
ENDLOOP.

ENDFORM. " excluir
*&---------------------------------------------------------------------*
*& Form buscar_ultimo_dia
*&---------------------------------------------------------------------*
* Busca el último día de un mes.
*----------------------------------------------------------------------*
* -->P_FECHA_LOW Primer día del mes
* <--P_FECHA_HIGH Último día del mes
*----------------------------------------------------------------------*
FORM buscar_ultimo_dia USING p_fecha_low
CHANGING p_fecha_high.

CALL FUNCTION 'RP_LAST_DAY_OF_MONTHS'
EXPORTING
day_in = p_fecha_low
IMPORTING
last_day_of_month = p_fecha_high
* EXCEPTIONS
* DAY_IN_NO_DATE = 1
* OTHERS = 2
.
IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
* WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
ENDIF.


ENDFORM. " buscar_ultimo_dia

jueves, 3 de enero de 2008

Mis 8

De El blog tecnológico de Blag me llegó una lista de ocho cosas que probablemente no sé de él, un meme de estos. En fin, mis ocho cosas:

· De pequeño quería ser inventor, después escritor, y después sólo quería estudiar matemáticas. Al final soy programador así que más o menos hago las tres cosas :D
· Aprendí a leer con 3 años. A atarme los zapatos con 7, y a atármelos bien con 21. A montar en bicicleta con 15.
· Escribí una novela sólo para regalarla.
· Cuando empecé con ABAP, pensé que era una mierda de lenguaje.
· Hice el camino de Santiago, y soy ateo.
· Leí el quinto libro de Harry Potter en el viaje de vuelta (que duró 9 horas)
· Leo mucho más de lo que escribo y publico, soy adicto a leer blogs así que de publicar, poquito. De esto sí os habréis dado cuenta :) [Una de las reglas de los blogs: antes de publicar, asegúrate de que no está ya publicado Vía: Microsiervos
· Misprogramasabap.blogspot.com tenía el propósito de ser mi libreta de apuntes personal de abap, así que me sorprende que la gente entre. Lo mismo paso del punto anterior y me animo. No le paso el relevo a nadie, soy así de soso (además no sabría a quién pasárselo).

Feliz año!!