Často je potřeba získat počet řádek, které obsahuje databázová tabulka. A jako obvykle k tomu vede více cest.
<?php
// neefektivní
$pocet = mysql_num_rows(mysql_query("SELECT * FROM tabulka"));
// rychlejší
$pocet = mysql_result(mysql_query("SELECT COUNT(*) FROM tabulka"), 0);
?>
První způsob je neefektivní proto, že SQL server se připraví na to, že bude vracet všechna data z tabulky, a připraví si na to potřebné struktury. Druhý způsob je naproti tomu velice rychlý, protože MySQL jenom vezme počet řádků tabulky, který si vede jako statistický údaj, a vrátí ho. Funkci mysql_num_rows je vhodné použít pouze v případě, kdy data z tabulky budeme tak jako tak potřebovat, tedy např.:
<?php
$result = mysql_query("SELECT * FROM tabulka");
echo "Celkový počet záznamů: " . mysql_num_rows($result) . "\n";
while ($row = mysql_fetch_assoc($result)) {
// zpracování tabulky
}
mysql_free_result($result);
?>
Další problém je potřeba vyřešit v případě, kdy sice chceme zjistit celkový počet řádků tabulky, ale chceme jich vypsat jen několik.
<?php
// neefektivní
$pocet = mysql_result(mysql_query("SELECT COUNT(*) FROM tabulka /* WHERE složitá podmínka */"), 0);
$result = mysql_query("SELECT * FROM tabulka /* WHERE složitá podmínka */ LIMIT $limit OFFSET $offset");
while ($row = mysql_fetch_assoc($result)) {
// zpracování řádku
}
mysql_free_result($result);
// taktéž neefektivní
$result = mysql_query("SELECT * FROM tabulka /* WHERE složitá podmínka */");
$pocet = mysql_num_rows($result);
if ($offset < $pocet) {
mysql_data_seek($result, $offset);
$i = 0;
while ($row = mysql_fetch_assoc($result)) {
// zpracování řádku
$i++;
if ($i >= $limit) {
break;
}
}
}
mysql_free_result($result);
// elegantní, ale jde použít pouze v MySQL a to až od verze 4
$result = mysql_query("SELECT SQL_CALC_FOUND_ROWS * FROM tabulka /* WHERE složitá podmínka */ LIMIT $limit OFFSET $offset");
$pocet = mysql_result(mysql_query(" SELECT FOUND_ROWS()"), 0);
while ($row = mysql_fetch_assoc($result)) {
// zpracování řádku
}
?>
První způsob je neefektivní pro dotazy se složitými podmínkami (např. vyhledávání podle masky) nebo složitě spojující více tabulek, druhý způsob je neefektivní pro vysoký $offset
. To, že je úloha získání celkového počtu řádků společně s vrácením jen několika z nich poměrně častá, si v MySQL uvědomili a nabídli pro ni efektivní, byť nestandardní řešení. Pokud ale aplikace nemusí pracovat nad více databázemi zároveň, není důvod se mu bránit.
Podobně laděné texty můžete najít i na autorově weblogu PHP triky.