在不加倍代码的情况下进行 count query 和 queryall?

Make count query and queryall without doubling the code?

我将 Yii 与 Firebird 一起使用。假设我们有以下代码:

    public function actionGetCustomer($limit = -1, $start = 0) {
            $arr = Yii::app()->db->createCommand()
                            ->select('*')
                            ->from('customer')
                            ->leftJoin('contact', 'customer.idcustomer = contact.idcontact')
                            ->limit($limit, $start)
                            ->queryAll();
            $ans['arr'] => $arr;
            return $ans;
    }

然后我们要计算数据库中的记录数并有以下内容:

    public function actionGetCustomer($limit = -1, $start = 0) {
            $arr = Yii::app()->db->createCommand()
                            ->select('*')
                            ->from('customer')
                            ->leftJoin('contact', 'customer.idcustomer = contact.idcontact')
                            ->limit($limit, $start)
                            ->queryAll();
            //copy & paste & edit
            $cnt = Yii::app()->db->createCommand()
                            ->select('count(*)')
                            ->from('customer')
                            ->leftJoin('contact', 'customer.idcustomer = contact.idcontact')
                            ->queryScalar();
            $ans['arr'] => $arr;
            $ans['cnt'] => $cnt;
            return $ans;
    }

并删除双倍代码(实际查询有 10 个连接和大量字段)是否有可能实现这样的目标?

    public function actionGetCustomer($limit = -1, $start = 0) {
            $cmd = Yii::app()->db->createCommand()
                            ->from('customer')
                            ->leftJoin('contact', 'customer.idcustomer = contact.idcontact');
            $arr = $cmd
                            ->select('*')
                            ->limit($limit, $start)
                            ->queryAll();
            //copy & paste & edit
            $cnt = $cmd
                            ->select('count(*)')
                            ->queryScalar();
            $ans['arr'] => $arr;
            $ans['cnt'] => $cnt;
            return $ans;
    }

试过了,但是来自数据库的答案被缓存了(?),尽管更改了 select 部分,查询标量返回的是先前查询的结果。还尝试克隆并手动将部分旧命令复制到新命令中,但出现错误。至于现在我看到的唯一选择是简单的 SQL.

注意第一个查询有限制,而第二个没有。

你可以像这样计算数组:

count($arr);

哪个会给你:

public function actionGetCustomer($limit = -1, $start = 0) {
        $arr = Yii::app()->db->createCommand()
                        ->select('*')
                        ->from('customer')
                        ->leftJoin('contact', 'customer.idcustomer = contact.idcontact')
                        ->limit($limit, $start)
                        ->queryAll();
        return array('arr'=>$arr,'cnt'=>count($arr));
}

正如下面评论中提到的,这并没有说明 LIMIT 语句。 如果您不介意在您的数据库上执行两次查询,您可以执行以下操作:

$resultCommand = Yii::app()->db->createCommand()
                        ->select('*')
                        ->from('customer')
                        ->leftJoin('contact', 'customer.idcustomer = contact.idcontact')
                        ->limit($limit, $start);
$countCommand = clone($resultCommand); //answer
$countCommand->setSelect('count(*)');
return array(
             'arr'=>$resultCommand->queryAll(),
             'cnt'=>$countCommand->queryScalar()
            );

如果您使用的是 MySQL,那么您可以使用 select 中的 SQL_CALC_FOUND_ROWS 字段,然后按 SELECT FOUND_ROWS ().基本上,这在以下示例中起作用:

SELECT SQL_CALC_FOUND_ROWS field1, fields2 FROM mytable
   WHERE fieldx ="somevalue" 
   LIMIT 20;

SELECT FOUND_ROWS();

在 yii 中,您会将代码转换为阅读:

$arr = Yii::app()->db->createCommand()
                 ->select('SQL_CALC_FOUND_ROWS (0), *')
                 ->from('customer')
                 ->leftJoin('contact', 'customer.idcustomer = contact.idcontact')
                 ->limit($limit, $start)
                 ->queryAll();

$totalRecords   =  Yii::app()->db->createCommand('SELECT FOUND_ROWS()')->queryScalar();