Busqueda Continua con SEEK

397 views
Skip to first unread message

esteban Micossi

unread,
Oct 22, 2013, 4:35:37 PM10/22/13
to publice...@googlegroups.com
Hola Grupo

Tengo una tabla con mas de 4 millones de registros (para los que son de argentina, es la base de datos de los contribuyentes de la AFIP), y necesito hacer una búsqueda por apellido y nombres y por el tamaño no conviene usar el LOCATE pues se hace muy lerdo y hasta se tilda, pues es lógico que use SEEK pero cuando pongo la búsqueda de un apellido por ejemplo "ANDRADA", necesito que me localice todos los ANDRADAS, y solamente me localiza el primero y allí termina. Como puedo hacer para que continue con los siguientes registros ?
Bueno amigos desde ya gracias
Saludos a todos
Esteban Micosii

Mauricio Gonzalez

unread,
Oct 22, 2013, 5:32:51 PM10/22/13
to publice...@googlegroups.com
Realmente estoy dando vueltas para tratar de entender que es lo que estas haciendo y que es lo que esperas hacer.
El SEEK, lo que hace es posicionarse del primer registro que encuentra la coincidencia, pero te invito a que te leas la ayuda de VFP, aunque sea un poquito, intentalo o aclara que es lo que intentas hacer.
Si quieres que el proceso continue barriendo con los demas registros, puedes combinar el SEEK y el SCAN
Ejemplo:
IF SEEK(ALLT(thisform.text1.value))  && Si encuentra coicidencia
....SCAN
........Proceso todos los demas registros a menos que tengas uno o varios condicionantes....
....ENDSCAN
ELSE     && No encuentra coicidencia
.......Proceso de no encuentra coicidencia
ENDIF

ZeRoberto

unread,
Oct 22, 2013, 5:35:11 PM10/22/13
to publicesvfoxpro
SET NEAR ON
SET KEY TO "CODIGO DE BUSQUEDA"

HernanCano

unread,
Oct 22, 2013, 5:39:41 PM10/22/13
to publice...@googlegroups.com
¿Eres programador?

use ARCHIVO shared noupdate
index on APELLIDO to TEMPOR.TEM compact
go top

if not seek(M.cApe,"ARCHIVO")
   =MessageBox("No encontrado")
else
   scan for alltrim(M.cApe) = alltrim(APELLIDO)
         ? alltrim(APELLIDO), alltrim(NOMBRE), alltrim(DOC_ID)
   endscan
endif

¿Sabes qué es M.cApe?

Fidel Charny

unread,
Oct 22, 2013, 5:40:51 PM10/22/13
to publice...@googlegroups.com
Eso es lo que hace Seek

Supongo que cargaste los datos a una tabla, que aquí llamo "Contribuyen".
Si estás usando SEEK, es porque tienes un índice sobre el campo del nombre (que aquí llamo "Nombre"), por lo que SELECT SQL trabajará muy rápido.

SELECT * FROM Contribuyen WHERE nombre="ANDRADA" INTO CURSOR losAndrada
select LosAndrada
browse


No utilices el comando SEEK. En su reemplazo emplea la función Seek() o Indexseek()
if indexseek("ANDRADA",.F.,"CONTRIBUYEN","INDNOMBRE")
        SELECT CONTRIBUYEN
        SET ORDER TO INDNOMBRE
        INDEXSEEK("ANDRADA",.T.,"CONTRIBUYEN","INDNOMBRE")
        DO WHILE LEFT(NOMBRE,LEN("ANDRADA"))="ANDRADA"
                 IF EOF()
                       EXIT
                 ENDIF
                 ? NOMBRE,CUIT
                 SKIP
         ENDDO
ENDIF

ZeRoberto

unread,
Oct 22, 2013, 5:42:12 PM10/22/13
to publicesvfoxpro
Usa SELECT SQL mejor pero crea bien los indices.

HernanCano

unread,
Oct 22, 2013, 5:46:03 PM10/22/13
to publice...@googlegroups.com
Roberto:
Tu respuesta no responde la pregunta del colega esteban.
Lo que se deba hacer es hacerle entender que después ubicar el primer registro con del primer SEEK, no puede hacer otro SEEK para ubicar el sgte.

Fernando D. Bozzo

unread,
Oct 22, 2013, 5:46:10 PM10/22/13
to publice...@googlegroups.com
Hola Esteban, creo que lo que comentás del LOCATE se puede deber a que no estés usando bien los índices. ¿Estás seguro que el LOCATE lo estás usando de forma optimizada con Rushmore? Porque al final lo que estás queriendo es simular el LOCATE/CONTINUE, y si se usa Rushmore la velocidad es la misma que la del SEEK y la del SQL.

¿Qué índices tenés y cómo estabas haciendo el LOCATE?


Saludos.-

Fernando D. Bozzo

unread,
Oct 22, 2013, 5:49:05 PM10/22/13
to publice...@googlegroups.com
Ah, una cosa más: Sería muy útil si copiaras en un post el resultado de LIST STATUS con la tabla abierta también (la parte que describe tablas e índices), ya que podría haber algo erróneo y ahí también se vería.

Saludos!

Antonio.xt

unread,
Oct 22, 2013, 6:34:54 PM10/22/13
to publice...@googlegroups.com

Es normal que el SEEK se posicione siempre en el primer registro encontrado, asi es como funciona; para el objetivo que persigues debes usar el SEEK para localizar el primer registro que coincida con la busqueda y luego hacer un SCAN WHILE {misma condicion de la busqueda del SEEK}, asi mientras los registros siguientes sean iguales, es decir, mientras el apellido sea "ANDRADA" segun tu ejemplo, se va a procesar y cuando ya no sea se sale del ciclo del SCAN WHILE.

Aunque no se realmente lo que necesites hacer, pero el tipo de busqueda que mencionas es esta.



El martes, 22 de octubre de 2013 15:35:37 UTC-5, esteban Micossi escribió:

Carlos Miguel FARIAS

unread,
Oct 22, 2013, 9:27:15 PM10/22/13
to Grupo Fox

SET NEAR ON
lcApellidoBusca = && de algún lado sale
lcApellidoTope = TRIM(lcApellidoBusca) +  CHR(255)
SCAN FOR BETWEEN(tabla.Apellido,lcApellidoBusca,lcApellidoTope)
ENDSCAN

esteban Micossi

unread,
Oct 22, 2013, 9:42:24 PM10/22/13
to publice...@googlegroups.com
Bien Muchachos.
Gracias a todos
En realidad es un proceso que hago tomando el archivo original que lo bajo de la AFIP (es un archivo plano) y tratar de tomar directamente los datos desde allí y volcarlos a un cursor pero se me hace algo engorroso y he decidido poner todo en una tabla y usar el SELECT * FROM que me sugiere Fidel y allí quedo todo OK.
Nuevamente agradezco a todos por la colaboración.
Les dejo un abrazo
Esteban Micossi

Edgar Acevedo

unread,
Oct 23, 2013, 1:07:37 AM10/23/13
to publice...@googlegroups.com
Se me ocurre esto:

1- Debes tener un TAG de índice ya creado en base al apellido. Por ejemplo:

USE MITABLA EXCLUSIVE
INDEX TAG APELLIDOS ON APELLIDOS

2- Debes "filtrar" todos aquellos que coincidan con el criterio a buscar pero SIN USAR el LOCATE.  Para este caso debes usar el SET KEY TO. Por ejemplo:

M.ApeBuscar = "ANDRADA"              && Para efectos de ejemplo hacemos esta asignación de variable
SET ORDER TO APELLIDOS               && Activas el TAG "apellidos" que ya deberías tener creado.
SET EXACT OFF                        && Desactivas el EXACT
SET KEY TO ALLTRIM(M.ApeBuscar)      && Activas el "filtro de registros"
GO TOP                               && Tratamos de ubicar el primer registro filtrado de "ANDRADA"
IF NOT EOF()                         && Si no llegó al final de archivo, logró filtrar a los "ANDRADA"
    BROWSE FIELDS APELLIDOS,NOMBRES  && Visualizamos todos los registros filtrados como "ANDRADA"
ENDIF
SET KEY TO                           && Para quitar el filtro
  
3- NO TE OLVIDES de quitar el filtro mediante un SET KEY TO cuando ya no lo necesites.

4- Por otro lado, si de forma "programática" deseas buscar alguien de nombre "CARLOS", entonces donde arriba te puse el BROWSE podrías hacer lo siguiente:

M.ApeBuscar = "ANDRADA"             

M.NomBuscar = "CARLOS"              
SET ORDER TO APELLIDOS              
SET EXACT OFF                       
SET KEY TO ALLTRIM(M.ApeBuscar)     
GO TOP                              
IF NOT EOF()                        
   LOCATE FOR ALLTRIM(M.NomBuscar) $ NOMBRES
   IF FOUND()
      M.Conteo = 0
      DO WHILE .T.
         M.Conteo = M.Conteo + 1
         ? TRANSFORM(M.Conteo, '999,999'), APELLIDOS, NOMBRE
         ? "Pulse una tecla para ubicar otro CARLOS ANDRADA o ESC para terminar."
         IF INKEY(0,'H') = 27
            EXIT
         ELSE
            CONTINUE
         ENDIF
      ENDDO
   ELSE
ENDIF
SET KEY TO

5- Finalmente, si desearas de una vez ubicar a todos los CARLOS ANDRADA, podrías anidar dentro del SET KEY TO un SET FILTER TO de esta manera:

M.ApeBuscar = "ANDRADA"             
M.NomBuscar = "CARLOS"              
SET ORDER TO APELLIDOS              
SET EXACT OFF                       
SET KEY TO ALLTRIM(M.ApeBuscar)     
GO TOP                              
IF NOT EOF()                        
   SET FILTER TO ALLTRIM(M.NomBuscar) $ NOMBRES
   GO TOP
   IF NOT EOF()
      BROWSE FIELDS APELLIDOS, NOMBRES
   ELSE
      ? "Habían apellidos ANDRADA, pero ninguno de nombre CARLOS".
   ENDIF
   SET FILTER TO
ENDIF
SET KEY TO

Yo he usado muy bien esta técnica con hasta medio millón de apellidos y nombres de personas en una tabla con 60 campos.  He tenido muy buena velocidad de respuesta (Tablas alojadas en un Servidor ClearOs, 22 estaciones usando las mismas tablas y todas ellas con procesadores INTEL CORE i3 y 4Gb RAM).  Pero no tengo idea de como se comportaría con 4 millones de registros y tus condiciones de hardware...

Saludos,


Edgar Acevedo

Arnaldo Toledano

unread,
Oct 23, 2013, 7:23:18 AM10/23/13
to publice...@googlegroups.com
Esteban
Cual es el link para bajar ese archivo ????

Gracias

Arnaldo
--
Reply all
Reply to author
Forward
0 new messages