Hlavní navigace

PHP okénko: Získání počtu řádek

Jakub Vrána

Druhý díl PHP okénka přináší drobný postřeh z programování v PHP, který se týká možných způsobů získání počtu řádek databázové tabulky.

Č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.

Našli jste v článku chybu?