php-如何获取GROUP BY查询的总行数?
从PDO手册中:
PDOStatement :: rowCount()返回 最后一个受影响的行数 DELETE,INSERT或UPDATE语句 由相应的执行 PDOStatement对象。
如果最后一条SQL语句执行 关联的PDOStatement是 SELECT语句,某些数据库可能 返回返回的行数 那句话。 但是这个 行为并不能完全保证 数据库,不应该依赖 用于便携式应用。
我是最近才发现的。 我刚刚将数据库抽象层更改为不再使用SELECT ... FROM,因为仅查询实际行然后对结果进行计数将更加有效。 现在PDO不支持!!
我不将PDO用于MySQL和PgSQL,但用于SQLite。 有没有办法(不完全改变dbal的后退)在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 COUNT(1) FROM替换SELECT ... FROM,然后仅返回该数字(效率很低,但仅适用于SQLite PDO)。 不过,这还不够好,因为在上面的示例查询中是GROUP BY,这将更改COUNT(1)的含义/功能。
Rudie asked 2020-07-21T17:40:19Z
11个解决方案
44 votes
这是给您的解决方案
$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];
RoboTamer answered 2020-07-21T17:40:29Z
24 votes
这有点内存不足,但是如果您仍在使用数据,我会经常使用它:
$rows = $q->fetchAll();
$num_rows = count($rows);
mjec answered 2020-07-21T17:40:49Z
8 votes
我最终使用的方法非常简单:
$query = 'SELECT a, b, c FROM tbl WHERE oele = 2 GROUP BY boele';
$nrows = $db->query("SELECT COUNT(1) FROM ($query) x")->fetchColumn();
可能不是最有效的方法,但它似乎是万无一失的,因为它实际上可以计算原始查询的结果。
Rudie answered 2020-07-21T17:41:14Z
4 votes
我不将PDO用于MySQL和PgSQL,但用于SQLite。 有没有办法(不完全改变dbal的后退)在PDO中对这样的行进行计数?
根据此评论,SQLite问题是由3.x中的API更改引入的。
就是说,您可能需要在使用PDO之前检查其实际实现功能。
我不熟悉它的内部结构,但对于PDO解析您的SQL(因为在数据库的日志中会出现SQL语法错误)的想法我会感到怀疑,更不用说试图对它做一点丝毫的意义以便计算行数了 使用最佳策略。
假设并非如此,要在select语句中返回所有适用行的计数的现实策略包括在SQL语句中对操作limit子句进行字符串操作,以及以下两种方法之一:
在其上运行select count()作为子查询(从而避免了您在PS中描述的问题);
打开一个游标,运行全部获取并计算行数; 要么
首先打开了这样一个游标,然后类似地计算剩余的行。
但是,更好的计数方法是执行完全优化的查询。 通常,这意味着重写您尝试分页的初始查询中有意义的部分-通过操作等去除不需要的字段和顺序。
最后,如果您的数据集足够大,可以计算任何类型的滞后,您可能还想研究返回从统计信息中得出的估计值,和/或定期将结果缓存在Memcache中。 在某些时候,精确地计数已经不再有用...
Denis de Bernardy answered 2020-07-21T17:42:15Z
2 votes
请记住,PDOStatement是Traversable。给定查询:
$query = $dbh->query('
SELECT
*
FROM
test
');
可以迭代以下内容:
$it = new IteratorIterator($query);
echo '
', iterator_count($it), ' items
';// Have to run the query again unfortunately
$query->execute();
foreach ($query as $row) {
echo '
', $row['title'], '
';}
或者,您可以执行以下操作:
$it = new IteratorIterator($query);
$it->rewind();
if ($it->valid()) {
do {
$row = $it->current();
echo '
', $row['title'], '
';$it->next();
} while ($it->valid());
} else {
echo '
No results
';}
Nev Stokes answered 2020-07-21T17:42:44Z
2 votes
如果您愿意放弃抽象的提示,则可以使用自定义包装器类,该类将所有内容直接传递给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 );
}
}
cwallenpoole answered 2020-07-21T17:43:04Z
1 votes
也许这将为您解决问题?
$FoundRows = $DataObject->query('SELECT FOUND_ROWS() AS Count')->fetchColumn();
tradyblix answered 2020-07-21T17:43:24Z
0 votes
您必须使用rowCount —返回受最后一条SQL语句影响的行数
$query = $dbh->prepare("SELECT * FROM table_name");
$query->execute();
$count =$query->rowCount();
echo $count;
Rahul Saxena answered 2020-07-21T17:43:44Z
0 votes
将查询结果放入数组中,可以执行count($ array)并在之后使用查询结果行呢? 例:
$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'];}
XaviQV answered 2020-07-21T17:44:04Z
0 votes
这是另一个问题,错误地提出了很多可怕的解决方案,所有这些问题都使解决一个不存在的问题变得极为复杂。
任何数据库交互的极其简单和明显的规则是
始终选择所需的唯一数据。
从这个角度来看,问题是错误的,接受的答案是正确的。 但是其他建议的解决方案也很糟糕。
问题是“如何错误地计数”。 一个人永远都不要直接回答这个问题,相反,唯一正确的答案是“一个人永远不要选择要对行进行计数的行。相反,总是请数据库为您对行进行计数。” 这个规则是如此明显,以至于无法看到如此多的尝试来打破它。
学习了此规则后,我们将看到这是一个SQL问题,甚至与PDO无关。 而且,如果从SQL角度正确地提出问题,答案将立即出现-DISTINCT。
$num = $db->query('SELECT count(distinct boele) FROM tbl WHERE oele = 2')->fetchColumn();
是这个特定问题的正确答案。
从上述规则的角度来看,开幕式海报本身的解决方案也是可以接受的,但总体而言效率较低。
Your Common Sense answered 2020-07-21T17:44:56Z
-1 votes
您可以通过两种方式来计算行数。
$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.
php-coder answered 2020-07-21T17:45:20Z