Подтвердить что ты не робот

Как получить общее количество строк запроса GROUP BY?

Из руководства PDO:

PDOStatement:: rowCount() возвращает количество строк, затронутых последним DELETE, INSERT или UPDATEвыполненный соответствующим Объект PDOStatement.

Если последний оператор SQL, выполняемый связанная с этим PDOStatement была SELECT, некоторые базы данных могут вернуть число строк, возвращаемых это утверждение. Однако это поведение не гарантировано для всех базы данных и не следует полагаться на для портативных приложений.

Я нашел это совсем недавно. Я только что изменил слой абстракции db, чтобы больше не использовать SELECT COUNT(1) ..., потому что просто запрос фактических строк, а затем подсчет результата будет намного более эффективным. И теперь PDO не поддерживает это!?

Я не использую PDO для MySQL и PgSQL, но я делаю это для SQLite. Есть ли способ (без полного изменения dbal back) для подсчета строк, подобных этому в PDO? В MySQL это будет примерно так:

$q = $db->query('SELECT a, b, c FROM tbl WHERE oele = 2 GROUP BY boele');
$rows = $q->num_rows;
// and now use $q to get actual data

С драйверами MySQLi и PgSQL это возможно. Со всем PDO это не так!?

PS. Моим первоначальным решением было расширить метод SQLResult- > count (мой собственный), чтобы заменить SELECT ... FROM на SELECT COUNT(1) FROM и просто вернуть это число (очень неэффективно, но только для SQLite PDO). Это не очень хорошо, потому что в примере, указанном выше, есть GROUP BY, который изменит значение/функцию COUNT(1).

4b9b3361

Ответ 1

Метод, который я использовал, очень прост:

$query = 'SELECT a, b, c FROM tbl WHERE oele = 2 GROUP BY boele';
$nrows = $db->query("SELECT COUNT(1) FROM ($query) x")->fetchColumn();

Может быть, не самый эффективный, но он кажется надежным, потому что он действительно учитывает исходные результаты запроса.

Ответ 2

Вот вам решение

$sql="SELECT count(*) FROM [tablename] WHERE key == ? ";
$sth = $this->db->prepare($sql);
$sth->execute(array($key));
$rows = $sth->fetch(PDO::FETCH_NUM);
echo $rows[0];

Ответ 3

Это немного неэффективно, но если вы все равно используете данные, я часто использую это:

$rows = $q->fetchAll();
$num_rows = count($rows);

Ответ 4

Я не использую PDO для MySQL и PgSQL, но я делаю это для SQLite. Есть ли способ (без полного изменения dbal back) для подсчета строк, подобных этому в PDO?

В соответствии с этот комментарий, проблема SQLite была введена с помощью изменения API в 3.x.

Тем не менее, вы можете проверить, как PDO фактически реализует функциональные возможности перед его использованием.

Я не знаком с его внутренними компонентами, но я был бы подозрителен в том, что PDO анализирует ваш SQL (поскольку синтаксическая ошибка SQL появится в журналах БД), не говоря уже о том, чтобы попытаться сделать хоть малейшее ощущение этого, чтобы для подсчета строк с использованием оптимальной стратегии.

Предполагая, что это не так, реалистичные стратегии для возврата количества всех применимых строк в выражении select включают в себя строковое манипулирование предложением limit из вашего оператора SQL и любой из следующих:

  • Выполнение select count() на нем как подзапрос (таким образом, вы избегаете проблемы, описанной в PS);
  • Открытие курсора, запуск fetch all и подсчет строк; или
  • Открыв такой курсор в первую очередь и аналогичным образом подсчитав оставшиеся строки.

Однако гораздо лучший способ подсчета будет выполнять полностью оптимизированный запрос, который будет делать это. Чаще всего это означает переписывание значимых фрагментов исходного запроса, который вы пытаетесь разбивать на страницы, - удаление ненужных полей и порядок операций и т.д.

Наконец, если ваши наборы данных достаточно велики, что учитывает любые задержки, вы также можете изучить вопрос о возврате оценки, полученной из statistics вместо этого и/или периодически кэширование результата в Memcache. В какой-то момент правильные подсчеты больше не полезны...

Ответ 5

Имейте в виду, что PDOStatement - Traversable. Учитывая запрос:

$query = $dbh->query('
    SELECT
        *
    FROM
        test
');

Его можно повторить:

$it = new IteratorIterator($query);
echo '<p>', iterator_count($it), ' items</p>';

// Have to run the query again unfortunately
$query->execute();
foreach ($query as $row) {
    echo '<p>', $row['title'], '</p>';
}

Или вы можете сделать что-то вроде этого:

$it = new IteratorIterator($query);
$it->rewind();

if ($it->valid()) {
    do {
        $row = $it->current();
        echo '<p>', $row['title'], '</p>';
        $it->next();
    } while ($it->valid());
} else {
    echo '<p>No results</p>';
}

Ответ 6

Если вы готовы отказаться от намека на абстракцию, вы можете использовать собственный класс-оболочку, который просто передает все до PDO. Скажем, что-то вроде этого: (Предупреждение, код не проверен)

class SQLitePDOWrapper
{
    private $pdo;

    public function __construct( $dns, $uname = null, $pwd = null, $opts = null )
    {
        $this->pdo = new PDO( $dns, $unam, $pwd, $opts ); 
    }
    public function __call( $nm, $args )
    {
        $ret = call_user_func_array( array( $this->pdo, $nm ), $args );
        if( $ret instanceof PDOStatement )
        {
            return new StatementWrapper( $this, $ret, $args[ 0 ] ); 
               // I'm pretty sure args[ 0 ] will always be your query, 
               // even when binding
        }

        return $ret;
    }

}

class StatementWrapper
{
    private $pdo; private $stat; private $query;

    public function __construct( PDO $pdo, PDOStatement $stat, $query )
    {
        $this->pdo  = $pdo;
        $this->stat = $stat;
        this->query = $query;
    }

    public function rowCount()
    {
        if( strtolower( substr( $this->query, 0, 6 ) ) == 'select' )
        {
            // replace the select columns with a simple 'count(*)
            $res = $this->pdo->query( 
                     'SELECT COUNT(*)' . 
                          substr( $this->query, 
                              strpos( strtolower( $this->query ), 'from' ) ) 
                   )->fetch( PDO::FETCH_NUM );
            return $res[ 0 ];
        }
        return $this->stat->rowCount();
    }

    public function __call( $nm, $args )
    {
        return call_user_func_array( array( $this->stat, $nm ), $args );
    }
}

Ответ 7

Может быть, это поможет вам?

$FoundRows = $DataObject->query('SELECT FOUND_ROWS() AS Count')->fetchColumn();

Ответ 8

Вы должны использовать rowCount - возвращает количество строк, затронутых последним оператором SQL

$query = $dbh->prepare("SELECT * FROM table_name");
$query->execute();
$count =$query->rowCount();
echo $count;

Ответ 9

Как разместить результаты запроса в массиве, где вы можете сделать подсчет (массив $) и использовать последующие строки запроса? Пример:

$sc='SELECT * FROM comments';
$res=array();
foreach($db->query($sc) as $row){
    $res[]=$row;
}

echo "num rows: ".count($res);
echo "Select output:";
foreach($res as $row){ echo $row['comment'];}

Ответ 10

Это еще один вопрос, который, будучи ошибочно поставлен, порождает множество ужасных решений, все усложняет задачу решения несуществующей проблемы.

Чрезвычайно простое и очевидное правило для любого взаимодействия с базой данных -

Всегда выбирайте только те данные, которые вам нужны.

С этой точки зрения вопрос неверен, и принятый ответ прав. Но другие предлагаемые решения просто ужасны.

Вопрос заключается в том, "как получить счет неправильно". Не следует отвечать на него просто, но вместо этого единственный правильный ответ: "Никогда не следует выбирать строки для их подсчета. Вместо этого ВСЕГДА попросите базу данных подсчитать строки для вас". Это правило настолько очевидно, что просто невероятно видеть, как многие пытаются его сломать.

Изучив это правило, мы увидим, что это вопрос SQL, даже не связанный с PDO. И, если бы его спросили правильно, с точки зрения SQL, ответ появился бы мгновенно - DISTINCT.

$num = $db->query('SELECT count(distinct boele) FROM tbl WHERE oele = 2')->fetchColumn();

- правильный ответ на этот конкретный вопрос.

Собственное решение открытия плаката также приемлемо с точки зрения вышеупомянутого правила, но будет менее эффективным в общих чертах.

Ответ 11

Есть два способа подсчета количества строк.

$query = "SELECT count(*) as total from table1";
$prepare = $link->prepare($query);
$prepare->execute();
$row = $prepare->fetch(PDO::FETCH_ASSOC);
echo $row['total']; // This will return you a number of rows.

Или второй способ

$query = "SELECT field1, field2 from table1";
$prepare = $link->prepare($query);
$prepare->execute();
$row = $prepare->fetch(PDO::FETCH_NUM);
echo $rows[0]; // This will return you a number of rows as well.