Hay ocasiones en las cuales se requiere obtener de las tablas una cantidad fija de filas, el caso más común es para mostrar esas filas en una grilla. Si por ejemplo una tabla tiene 450.000 filas, escribir un SELECT que te traiga esas 450.000 filas sería un gran error, y por varios motivos:
- Ningún usuario mirará tantas filas
- Habrá muchísimo tráfico en la red, innecesariamente. Eso la volverá lenta
- Si varios usuarios están ejecutando ese SELECT, puedes llegar a saturar la red
- El usuario tardará mucho en obtener las filas que quiere ver
Para solucionar esos problemas es usual utilizar una técnica llamada paginación.
Por ejemplo, en la grilla muestras las primeras 100 filas, si el usuario quiere ver las siguientes 100 filas, entonces debe hacer clic en un botón. Cada vez que hace clic en ese botón se le muestran 100 filas más.
¿Cuáles son las ventajas de la paginación?
- La cantidad de filas que se obtienen del SELECT es relativamente pequeña (en nuestro ejemplo, serían 100 filas)
- La velocidad es muy alta (no es lo mismo obtener 100 filas que obtener 450.000 filas)
- No perjudicas a los demás usuarios
Casi todos los motores SQL ofrecen una forma sencilla de hacer paginación. Por ejemplo, en Firebird se escribiría:
Listado 1. Haciendo paginación en Firebird. Obteniendo las primeras 100 filas
SELECT * FROM MiTabla ROWS 1 TO 100
Listado 2. Haciendo paginación en Firebird. Obteniendo las siguientes 100 filas
SELECT * FROM MiTabla ROWS 101 TO 200
En el Listado 1. y en el Listado 2. vemos como se pueden obtener la cantidad de filas que se desean cuando usamos Firebird. Es muy fácil.
Lamentablemente, el comando SELECT del Visual FoxPro no cuenta con esta posibilidad. Sin embargo podemos hacer paginación usando un truco. Y para ello haremos uso de una subconsulta.
La tabla de CLIENTES
Captura 1. Las filas de la tabla CLIENTES
Haciendo paginación con Visual FoxPro
Como nativamente el Visual FoxPro no nos permite hacer paginación, crearemos un procedimiento que se encargará de esa tarea.
Este PROCEDURE (salvo algunas pequeñas modificaciones estéticas realizadas por el autor de este blog) ha sido compartido por Víctor Hugo Espínola de Paraguay, en el grupo RinconFox del Whatsapp. Muchas gracias Víctor Hugo, muy buen aporte.
Listado 3. Un PROCEDURE para poder hacer paginación
PROCEDURE PAGINA_SELECT LPARAMETERS tcTabla, tcIdentificador, tcOrdenarPor, tnTamanoPagina, tnPaginaNro LOCAL lnFilasExcluidas, lcCondicionWhere, lcConsulta, llConsultaOK *--- tcTabla : La tabla que contiene los datos *--- tcIdentificador: La Primary Key o Unique Key de la tabla *--- tcOrdenarPor : La columna (o columnas) por las cuales se desea ordenar a la tabla *--- tnTamanoPagina : El tamaño de cada página, o sea, la cantidad de filas por página *--- tnPaginaNro : El número de la página que se desea extraer tnTamanoPagina = Max(tnTamanoPagina, 1) && Para asegurar que la Página tenga al menos una fila tnPaginaNro = Max(tnPaginaNro, 1) && Para asegurar que el Número de la Página sea al menos 1 *--- lnFilasExcluidas: La cantidad de filas que estarán excluidas *--- lcCondicionWhere: La condición para mostrar o no la primera página lnFilasExcluidas = (tnPaginaNro - 1) * tnTamanoPagina lcCondicionWhere = Iif(lnFilasExcluidas = 0, "WHERE 1=0", "") TEXT TO M.lcConsulta NOSHOW TEXTMERGE PRETEXT 15 SELECT TOP <> * FROM <> WHERE <> NOT IN (SELECT TOP <> <> FROM <> <> ORDER BY <>) ORDER BY <> ENDTEXT =MessageBox(M.lcConsulta) =ExecScript(M.lcConsulta) ENDPROC * *
Ejemplos de uso
Para hacerlo sencillo, en los siguientes ejemplos cada página tendrá 3 filas. Eso significa que en la primera página estarán las filas del 1 al 3, en la segunda página las filas del 4 al 6, en la tercera página las filas del 7 al 9, etcétera.
Ejemplo 1. Para ver la primera página
DO PAGINA_SELECT WITH «CLIENTES», «CLI_IDENTI», «CLI_NOMBRE», 3, 1
Captura 2. La consulta que ejecutará el Visual FoxPro
La condición de la subconsulta siempre dará falso como resultado, porque 1 siempre será diferente que 0. Eso significa que ninguna fila se obtendrá de la subconsulta, porque siempre estará totalmente vacía. Por lo tanto, la columna CLI_IDENTI nunca se encontrará en esa subconsulta y en consecuencia se mostrarán las 3 primeras filas de la tabla CLIENTES.
¿Entiendes la lógica empleada allí?
NOTA: En lugar de escribir 1 = 0 también se podría haber escrito .F., pero hay una diferencia y es que 1 = 0 funcionará en cualquier motor SQL cuando queremos establecer una condición como falsa, en cambio .F. solamente funcionará en Visual FoxPro.
Captura 3. La primera página de la tabla CLIENTES
Puedes comparar la Captura 1. con la Captura 3., para comprobar que efectivamente se están mostrando los tres primeros clientes.
Ejemplo 2. Para ver la segunda página
DO PAGINA_SELECT WITH «CLIENTES», «CLI_IDENTI», «CLI_NOMBRE», 3, 2
Captura 4. La consulta que ejecutará el Visual FoxPro
En este caso, la subconsulta devuelve las 3 primeras filas de la tabla CLIENTES. Y la condición en la cláusula WHERE es que el valor de la columna CLI_IDENTI no se encuentre ahí. En otras palabras, se excluirán de la tabla CLIENTES sus tres primeras filas. Eso implica que el SELECT principal tomará las 3 primeras filas, empezando a contar desde la cuarta fila de la tabla CLIENTES. Ingenioso ¿verdad?
Captura 5. La segunda página de la tabla CLIENTES
Ejemplo 3. Para ver la tercera página
DO PAGINA_SELECT WITH «CLIENTES», «CLI_IDENTI», «CLI_NOMBRE», 3, 3
Captura 6. La consulta que ejecutará el Visual FoxPro
Aquí, la subconsulta devuelve las 6 primeras filas de la tabla CLIENTES. Y la condición en la cláusula WHERE es que el valor de la columna CLI_IDENTI no debe encontrarse en ninguna de esas 6 filas. Son excluidas. Por lo tanto el TOP 3 del SELECT principal mostrará las filas 7, 8, y 9.
Captura 7. La tercera página de la tabla CLIENTES
Y así podríamos continuar con las siguientes páginas. Para hacerlo corto, veamos la última página que tiene datos, que en nuestro ejemplo es la página número 6.
Ejemplo 4. Para ver la sexta página
DO PAGINA_SELECT WITH «CLIENTES», «CLI_IDENTI», «CLI_NOMBRE», 3, 6
Captura 8. La consulta que ejecutará el Visual FoxPro
Captura 9. La sexta página de la tabla CLIENTES
Nuestra tabla de CLIENTES tiene 16 filas (como puedes comprobar volviendo a mirar la Captura 1.). En la Captura 8. las primeras 15 filas son excluidas por la condición que se ha puesto en la cláusula WHERE. Por lo tanto se deberían mostrar las siguientes 3 filas. Pero como solamente queda una fila, ya que la tabla tiene 16 filas y 15 filas fueron excluidas, se mostrará una sola fila, tal y como puedes ver en la Captura 9.
Con estos ejemplos, hemos verificado que el PROCEDURE que se escribió en el Listado 3. funciona perfectamente bien.
Conclusión:
Traer todas las filas de una tabla muchas veces no es práctico ni recomendable, sobre todo cuando esas filas deben ser mostradas a los usuarios, porque ningún usuario estará mirando miles y miles de filas.
Una técnica para mostrar solamente unas cuantas filas, y siempre la misma cantidad de filas, es la paginación.
Mediante esta técnica se divide imaginariamente a la tabla en partes iguales, cada una de esas partes recibe el nombre de página.
La cantidad de filas de cada página la determina el programador, según lo que sea más adecuado a sus necesidades.
Por ejemplo, cada página podría tener 50 filas. En la grilla se le muestran las 50 primeras filas de la tabla. Si quiere ver las siguientes 50 filas entonces debe hacer clic en un botón y allí vería desde la fila 51 hasta la fila 100. Si quiere ver las siguientes 50 filas entonces debe hacer clic en el botón y allí vería desde la fila 101 hasta la fila 150. Y así sucesivamente.
Desde luego que también podría tener un botón para ver la página anterior.
De esta manera, nunca se extraerían de la tabla más de 50 filas y en la grilla por lo tanto, nunca se verían más de 50 filas.
Los motores SQL tienen nativamente una cláusula que permite hacer paginación. Lamentablemente, ese no es el caso con Visual FoxPro. Pero se puede escribir un PROCEDURE que permita hacer paginación, tal y como se mostró en el Listado 3.
La paginación es muy, pero muy, importante. Deberías emplearla en cada ocasión posible.
Artículos relacionados:
De DBF a SQL (1). Introducción
De DBF a SQL (2). Reemplazando comandos
De DBF a SQL (3). Entendiendo a los cursores
De DBF a SQL (4). Ejemplos de usar SELECT con una sola tabla
De DBF a SQL (5). Las funciones agrupadas
De DBF a SQL (6). Agrupando filas
De DBF a SQL (7). Poniéndoles condiciones a los grupos
De DBF a SQL (8). Ordenando las filas
De DBF a SQL (9). Uniendo tablas
De DBF a SQL (10). Obteniendo las primeras filas de una tabla
De DBF a SQL (11). Relacionando una tabla con otra tabla
De DBF a SQL (12). Relacionando una tabla consigo misma
De DBF a SQL (13). Relacionando a varias tablas entre sí
De DBF a SQL (14). Más sobre el uso de DISTINCT
De DBF a SQL (15). Usando subconsultas
De DBF a SQL (16). Más sobre las subconsultas
De DBF a SQL (17). Ejemplos de subconsultas
De DBF a SQL (19). Hallando los porcentajes sobre un total
De DBF a SQL (20). Los operadores especiales de comparación
De DBF a SQL (21). La técnica de los dos cursores
De DBF a SQL (22). Optimizando el uso del operador de comparación especial IN
De DBF a SQL (23). Usando la función CAST()
De DBF a SQL (24). Buscando texto
De DBF a SQL (25). Creando tablas y cursores
De DBF a SQL (26). INSERT, UPDATE, y DELETE, con subconsultas
De DBF a SQL (27). Entendiendo Cliente/Servidor
De DBF a SQL (28). Conectándose a un Servidor
De DBF a SQL (29). Las cadenas de conexión ODBC a los motores SQL más populares
De DBF a SQL (30). Conectándose mediante ADO a las bases de datos
De DBF a SQL (31). Optimizando la escritura de los SELECT
De DBF a SQL (32). Mejorando la estética de los SELECT
De DBF a SQL (33). Usando la función SQLEXEC()
De DBF a SQL (34). Enviándole parámetros a la función SQLEXEC()
El índice del blog VFPavanzado