Page 1 of 1

otra solucion??

Posted: Thu Dec 21, 2006 12:08 pm
by Elias Torres
Hola a todos...

Vamos a ver si me podeis echar una mano...

Tengo el siguiente código que realiza una combinacion de tres tablas (articulo.dbf,stock.dbf,precios.dbf) y el resultado lo guarda en otra tabla llamada temporal.dbf dependiendo de dos variables: id_almacen y lista_precios. El codigo funciona perfectamente pero el tiempo que tarda es bastante y queria saber si alguien tiene alguna idea mejor de como poder optimizarlo para que tarde menos... Se lo agradecería!!



articulo->(dbgotop())
precios->(dbgotop())
stock->(dbgotop())

SELECT articulo

DO WHILE !EOF()

cod:=articulo->codart
nom:=articulo->nomart
codbar:=articulo->codbarart

&&busco en stock.dbf los articulos q tengan el id_almacen y el codigo
&&igual al codigo del la tabla de articulo
&&y me quedo con las existencias

IF stock->(DbSeek((id_almacen+cod),.t.))
s:=stock->cantex
ELSE
s:=0
ENDIF

&&busco en precios.dbf los articulos q tengan la lista de precios y el codigo
&&igual al codigo del la tabla de articulo
&&y me quedo con el precio

IF precios->(DbSeek((cod+lista_precios),.t.))
p:=precios->pvp
ELSE
p:=0
ENDIF

temporal->(dbappend())
temporal->codart:=cod
temporal->nomart:=nom
temporal->codbarart:=codbar
temporal->pvp:=p
temporal->existencia:=s
temporal->almacen:=id_almacen
articulo->(dbskip())
ENDDO


Saludos y gracias...

Elías Torres.

Posted: Thu Dec 21, 2006 1:34 pm
by Antonio Linares
Elías,

Prueba la aplicación en un directorio del Pocket PC que no sea la tarjeta de memoria y verás que la velocidad es mejor.

Posted: Thu Dec 21, 2006 1:42 pm
by Elias Torres
Antonio, puedes ponerme un ejemplo de como seleccionar un directorio del pocket que no sea de la tarjeta de memoria??

Que significa entonces (curdir()+'\.....'), no quiere decir que nos encontramos en el directorio raiz?? O estoy accediendo a la tarjeta de memoria?..


Saludos y gracias.

Elías Torres.

Posted: Thu Dec 21, 2006 1:48 pm
by Antonio Linares
Elías,

Cuando usas el emulador y compartes una carpeta del PC, esa carpeta compartida es la tarjeta de memoria en el emulador.

Lo que has de hacer es copiar los ficheros, ir a "My Device" y "pegarlos" alli, bien en el directorio raiz ó en una carpeta que crees. Para copiarlos pulsa sobre su nombre y mantén pulsado y te saldrá un menu con la opción de copiar.

CurDir() significa el directorio actual.

Posted: Thu Dec 21, 2006 1:54 pm
by Antonio Linares
Image
Image

Posted: Thu Dec 21, 2006 4:18 pm
by Elias Torres
Antonio,

yo estoy usando directamente una pda no el emulador. El proyecto lo tengo en My Documents\Trabajo\... Supongo que esto no use la tarjeta de memoria... no lo se.

De todas formas el uso de dos 'seek' en el código que he puesto más arriba implica que el tiempo de respuesta sea mayor.. puesto que tiene que hacer dos busqueda por cada registro de la tabla articulo. Esto mismo no se puede hacer como en FoxPro??

Por ejemplo:

Select campo1,campo2;
from tabla1,tabla2,tabla3;
where campo1.tabla1=campo1.tabla2......;
order by campo1

o algo parecido??

Saludos.

Elías Torres.

Posted: Thu Dec 21, 2006 5:47 pm
by Antonio Linares
Elías,

Es que FoxPro admite SQL directamente, algo que de momento no tiene Harbour. Asi que tienes que hacerlo como tu haces, de todas formas podrías crear un índice temporal por una determinada condición (INDEX ... FOR ... WHILE ... ) y siempre el trabajar con índices es más rápido.

Posted: Thu Dec 21, 2006 10:01 pm
by R.F.
haz probado hacer un SET RELATION ?, el problema es que se pierde mucho tiempo en las busquedas cada vez que haces un DBSEEK() en cambio con una relacion las cosas te funcionarian bastante mas rapido porque no tendrias necesidad de hacer busquedas, el set relation te maneja acceso directo a _ relacionado.

Posted: Fri Dec 22, 2006 9:13 am
by Elias Torres
Hola Rene, no he probado tu solución porque no se como montar los set relations... Podrias ponerme un ejemplo por favor que me pueda servir de guia?? Te lo agradeceria...


Saludos..

Elías Torres.

Posted: Fri Dec 22, 2006 6:12 pm
by R.F.
Veamos:

SET RELATION es uno de los comandos mas poderosos de DBASE (ojo, DBASE), pero es uno de los mas desaprovechados porque poca gente sabe como usarlo.

SET RELATION se utiliza para "relacionar" campos de de una base de datos "padre" contra uno o _ en bases de datos "hijas"

Cuando se establece una relacion entre 2 o mas tablas, cada vez que el puntero se mueva en la base de datos "padre" se movera automaticamente en las bases de datos relacionadas, apuntando al campo sobre el cual tiene establecida la relacion.

Requisitos:

1) que la base de datos "hija" este indexada sobre el campo sobre el cual se realiza la relacion.
2) que el campo sobre el cual se realiza la relacion en base de datos hija sea del mismo tipo y tamaño que su correspondiente en la base de datos padre
3) Condicion necesaria, no indispensable, que el campo tenga el mismo nombre tanto en la base de datos hija, como en la base de datos padre.

Uso:

1) Abrir las bases de datos hijas ANTES de abrir la base de datos padre, asignar su indice sobre el campo a relacionar:

USE PRECIOS
SET INDEX TO CVEPROD //suponiendo que exista un campo cveprod
USE STOCK
SET INDEX TO CVEPROD

USE ARTICULO // base de datos padre
/* establecemos la relacion:*/
SET RELATION TO cveprod INTO STOCK
SET RELATION TO cveprod INTO PRECIOS ADDITIVE

De esta manera, relacionamos el campo CVEPROD de la base de datos padre, contra _ CVEPROD de las bases de datos hijas

Para hacer referencia a _ de las bases de datos hijas, lo haremos por su respecitvo alias:

articulo->campo //en la base de datos padre
precios->campo // en la base de datos hija
stock->campo // en la base de datos hija.

cuando el puntero se mueve en la base de datos padre, en la base de datos hija se mueve, para hacerlo coincidir con el campo que tiene el mismo valor en la base de datos padre, es decir, la relacion "sincronza" _ y por ello es necesario que la base de datos hija este indexada.

Si no existe un registro en la base de datos hija, que coincida con un registro en la base de datos padre, la refencia hija->campo apuntara a EOF().

Locate y SET RELATION

Posted: Sat Dec 23, 2006 8:52 pm
by FiveWiDi
Rene, perdona el abuso, pero

¿Cómo se realizaría un LOCATE sobre una 'relación' de 3 bases de datos?

Tengo una rutina que automáticamente 'monta' el locate según _ que escoge el operador, y claro el uso de SET RELATION sería fantástico si supiera como 'montar' el LOCATE adecuado para _ de bases relacionadas.

Bueno lo más importante:

FELIZ NAVIDAD A TODOS

Carlos Gelabert

Posted: Tue Dec 26, 2006 5:39 pm
by R.F.
Se pueden montar hasta 6 niveles de relacione donde un padre, puede ser al mismo tiempo hijo de otra base de datos de padre:

Ejemplo

USE nieto
SET INDEX tO.....

USE padre
SET INDEX TO
SET RELATION TO nieto INTO campocomun

USE ABUELO
SET INDEX TO....
SET RELATION TO padre INTO campocomunpadre

Cuand el apuntador se mueve en la tabla "abuelo", se mueve tambien en la tabla padre, y cuando se mueve en la padre por logica se mueve en la nieta.

Para obtener un valor de una tabla relacionada hasta este tercer nivel, se hace:

abuelo->padre->nieto->campo

y se puede leer perfectamente la relacion.

Posted: Wed Dec 27, 2006 12:08 pm
by Elias Torres
Rene,

He probado lo que me has dicho pero el resultado no es correcto...

El codigo que tengo es este:

SELECT 0
USE (CURDIR()+"\temporal.dbf") VIA "DBFCDX" new
INDEX ON codbarart+codart+nomart TO temporal
temporal->( OrdSetFocus( "codbarart+nomart+codart" ) )


SELECT 0
USE (CURDIR()+"\precios.dbf") VIA "DBFCDX" new
SET INDEX TO articulo+numero

SELECT 0
USE (CURDIR()+"\stock.dbf") VIA "DBFCDX" new
SET INDEX TO artex+almex

SELECT 0
USE (CURDIR()+"\articulo.dbf") VIA "DBFCDX" new
INDEX ON codart TO codart
articulo->(OrdSetFocus( "codart"))
SET RELATION TO "articulo+lista_precios" INTO precios
SET RELATION TO "artex+id_almacen" INTO stock ADDITIVE

SELECT articulo
DO WHILE !EOF()
temporal->(dbappend())
temporal->codart:=articulo->codart
temporal->nomart:=articulo->nomart
temporal->codbarart:=articulo->codbarart
temporal->pvp:=precios->pvp
temporal->existencia:=stock->cantex
temporal->almacen:=id_almacen
articulo->(dbskip())
ENDDO

El resultado final no es correcto puesto que en temporal->pvp y en temporal->existencia (los _ que utilizo cuando busco en stock y en precios) el valor que tiene despues de hacer todo es cero...

Supongo que el tema viene porque en la tabla de stock a parte de buscar por el articulo tengo que buscar por otro valor llamado id_almacen... Igual ocurre con la tabla de precios puesto que a parte de buscar por el articulo tengo que hacerlo por otra variable que se llama id_almacen, es decir que la busqueda debe contener tres valores... el codigo, el almacen y la lista de precios, puesto que en la tabla stock tengo varios id_almacen y en la de precios tengo varias lista_precios...

La verdad es que el tiempo ha mejorado pero aun no me hace lo que necesito....


Alguna idea?

Saludos

Elías Torres.