CakePHP:在用find方法构建查询时,我如何使用“HAVING”操作?

7vux5j2d  于 2022-11-12  发布在  PHP
关注(0)|答案(6)|浏览(110)

我尝试在使用CakePHP paginate()方法的SQL查询中使用“HAVING”子句。
经过一番搜索后,看起来这不能通过Cake的paginate()/find()方法实现。
我的代码看起来像这样:

$this->paginate = array(
        'fields' => $fields,
        'conditions' => $conditions,
        'recursive' => 1,
        'limit' => 10, 
        'order' => $order,
        'group' => 'Venue.id');

其中一个$字段是别名“distance”。我想添加一个当distance〈25时的查询(例如,HAVING distance〈25)。
到目前为止,我已经看到了两种解决方案,不幸的是,这两种方案都不符合我的需要。
1)在“group”选项中添加HAVING子句。例如'group' => 'Venue.id HAVING distance < 25'。当与分页一起使用时,这似乎不起作用,因为它会打乱执行的初始计数查询。(即尝试SELECT distinct(Venue.id HAVING distance < 25),这显然是无效的语法。)
2)在WHERE条件之后添加HAVING子句(例如WHERE 1 = 1 HAVING field > 25)这不起作用,因为HAVING子句似乎必须出现在Group语句之后,而Cake在它生成的查询中将其放置在WHERE条件之后。
有没有人知道用CakePHP的find()方法来实现这一点?我不想使用query(),因为这会涉及到大量的返工,也意味着我需要实现我自己的分页逻辑!
先谢谢你

xu3bshqb

xu3bshqb1#

你必须把它和团体条件放在一起。就像这样

$this->find('all', array(
    'conditions' => array(
        'Post.length >=' => 100
    ),
    'fields' => array(
        'Author.id', 'COUNT(*) as Total'
    ),
    'group' => array(
        'Total HAVING Total > 10'
    )
));

希望对你有帮助

zbdgwd5y

zbdgwd5y2#

我使用了以下技巧在WHERE子句的末尾添加了自己的HAVING子句。cake子查询文档中提到了“dbo-〉expression()”方法。

function addHaving(array $existingConditions, $havingClause) {
  $model = 'User';
  $db = $this->$model->getDataSource();

  // Two fun things at play here,
  // 1 - mysql doesn't allow you to use aliases in WHERE clause
  // 2 - Cake doesn't allow a HAVING clause separate from a GROUP BY
  // This expression should go last in the WHERE clause (following the last AND)
  $taut = count($existingConditions) > 0 ? '1 = 1' : '';
  $having = $db->expression("$taut HAVING $havingClause");

  $existingConditions[] = $having;

  return $existingConditions;
}
jjhzyzn0

jjhzyzn03#

根据手册,CakePHP/2最后支持having。它在2017年7月22日作为查找数组参数添加到版本2.10.0,released
从《2.10迁移指南》:
Model::find()现在支持havinglock选项,这些选项使您能够将HAVINGFOR UPDATE锁定子句添加到查找操作中。

e5nszbig

e5nszbig4#

我知道,一个人不应该修改内部代码,但如果你打开PaginatorComponent并修改第188行:

$count = $object->find('count', array_merge($parameters, $extra));

更改为:

$count = $object->find(
             'count', 
             array_merge(array("fields" => $fields),$parameters, $extra)
         );

一切都将被修复。您将能够将HAVING子句添加到'group'中,COUNT(*)将不会成为问题。
或者,作行:

$count = $object->paginateCount($conditions, $recursive, $extra);

要将$fields

$count = $object->paginateCount($fields,$conditions, $recursive, $extra);

之后,您可以“覆盖”模型上的方法,并确保在find()中包含$字段,就这样!,=P

zbq4xfa0

zbq4xfa05#

这里有另一个想法,它不能解决分页问题,但它很干净,因为它只是覆盖了AppModel中的find命令。只需在查询中添加一个group和having元素,这将转换为HAVING子句。

public function find($type = 'first', $query = array()) {
    if (!empty($query['having']) && is_array($query['having']) && !empty($query['group'])) {
      if ($type == 'all') {
        if (!is_array($query['group'])) {
          $query['group'] = array($query['group']);
        }

        $ds = $this->getDataSource();
        $having = $ds->conditions($query['having'], true, false);
        $query['group'][count($query['group']) - 1] .= " HAVING $having";

        CakeLog::write('debug', 'Model->find: out query=' . print_r($query, true));
      } else {
        unset($query['having']);
      }
    }

    return parent::find($type, $query);
  }

在这里找到的
https://groups.google.com/forum/?fromgroups=#!topic/tickets-cakephp/EYFxihwb55I

ee7vknir

ee7vknir6#

在find中使用'having'对我来说不起作用。相反,我把一个字符串与组“group =〉product_id,color_id having sum(quantity)〉2000“放在一起,就像一个魔咒。使用CakePHP 2.9

相关问题