Un caso típico
en el desarrollo web con PHP y MySQL es
la funcionalidad de paginar resultados, si bien no es algo difícil muchos
desperdician la potencialidad y malgastan los recursos de MySQL.
Para paginar resultados necesitamos saber 3 valores:
Para paginar resultados necesitamos saber 3 valores:
1.
Número de Página:
este valor lo pide el usuario, así que es fácil obtenerlo.
2.
Total de registros
por página: normalmente lo define el programador con una constante
3.
Total de registros:
necesitamos saber el total de registros para poder crear la cantidad de enlaces
necesarios por página.
Donde se desperdicia el potencial y malgasta recurso de MySQL normalmente es en el 3 valor. Pues muchos ejecutan una consulta con LIMIT y otra consulta con un COUNT sin el LIMIT. Y es allí donde es el error, ya que MySQL ofrece las funciones: SQL_CALC_FOUND_ROWS yFOUND_ROWS.
·
SQL_CALC_FOUND_ROWS: calcula el número de resultados de una consulta
sin LIMIT.
·
FOUND_ROWS: obtiene el resultado del último
SQL_CALC_FOUND_ROWS ejecutados.
Aunque con estas funciones debemos igual ejecutar dos consultas, el cálculo y tiempo de respuesta es mucho más rápido que haciéndolo con COUNT.
Ejemplo
Código:
<?php
$link = @mysql_connect("servidor", "usuario", "password");
mysql_select_db("base_de_datos", $link);
// máximo por página
$limit = 5;
// pagina pedida
$pag = (int) $_GET["pag"];
if ($pag < 1)
{
$pag = 1;
}
$offset = ($pag-1) * $limit;
$sql = "SELECT SQL_CALC_FOUND_ROWS id, nombre FROM tabla LIMIT $offset, $limit";
$sqlTotal = "SELECT FOUND_ROWS() as total";
$rs = mysql_query($sql);
$rsTotal = mysql_query($sqlTotal);
$rowTotal = mysql_fetch_assoc($rsTotal);
// Total de registros sin limit
$total = $rowTotal["total"];
?>
$link = @mysql_connect("servidor", "usuario", "password");
mysql_select_db("base_de_datos", $link);
// máximo por página
$limit = 5;
// pagina pedida
$pag = (int) $_GET["pag"];
if ($pag < 1)
{
$pag = 1;
}
$offset = ($pag-1) * $limit;
$sql = "SELECT SQL_CALC_FOUND_ROWS id, nombre FROM tabla LIMIT $offset, $limit";
$sqlTotal = "SELECT FOUND_ROWS() as total";
$rs = mysql_query($sql);
$rsTotal = mysql_query($sqlTotal);
$rowTotal = mysql_fetch_assoc($rsTotal);
// Total de registros sin limit
$total = $rowTotal["total"];
?>
<table border="1" bordercolor="#000">
<thead>
<tr>
<td>Id</td>
<td>Nombre</td>
</tr>
</thead>
<tbody>
<?php
while ($row = mysql_fetch_assoc($rs))
{
$id = $row["id"];
$name = htmlentities($row["nombre"]);
?>
while ($row = mysql_fetch_assoc($rs))
{
$id = $row["id"];
$name = htmlentities($row["nombre"]);
?>
<tr>
<td>
<?php echo $id; ?>
</td>
<td>
<td>
<?php echo $name; ?>
</td>
</tr>
</tr>
<?php
}
?>
}
?>
</tbody>
<tfoot>
<tr>
<td colspan="2">
<?php
$totalPag = ceil($total/$limit);
$links = array();
for( $i=1; $i<=$totalPag ; $i++)
{
$links[] = "<a href=\"?pag=$i\">$i</a>";
}
echo implode(" - ", $links);
?>
$totalPag = ceil($total/$limit);
$links = array();
for( $i=1; $i<=$totalPag ; $i++)
{
$links[] = "<a href=\"?pag=$i\">$i</a>";
}
echo implode(" - ", $links);
?>
</td>
</tr>
</tfoot>
</table>
Advertencia:
·
En la configuración
de PHP (php.ini) el valor mysql.trace_mode debe estar en Off. Si está en On por
cada consulta que se haga a MySQL se ejecuta un explain y esto hace
sql_calc_found_rows inutil, por ende, found_rows siempre retornara 0. Este
valor normalmente está en off, pero cabe la advertencia.