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

问题描述 投票:0回答:6

我正在尝试使用 CakePHP paginate() 方法在 SQL 查询中使用“HAVING”子句。

经过一番搜索,似乎无法通过 Cake 的 paginate()/find() 方法来实现。

我的代码看起来像这样:

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

其中一个 $fields 是别名“distance”。我想添加一个查询何时距离 < 25 (e.g. 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 子句必须位于 Cake 在其生成的查询中的 WHERE 条件之后放置的组语句after

有谁知道如何使用 CakePHP 的 find() 方法来做到这一点?我不想使用 query(),因为这会涉及大量返工,也意味着我需要实现自己的分页逻辑!

提前致谢

php mysql cakephp cakephp-2.x
6个回答
36
投票

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

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

希望对你有帮助


1
投票

我使用以下技巧在 WHERE 子句末尾添加我自己的 HAVING 子句。蛋糕子查询文档中提到了“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;
}

1
投票

根据手册,CakePHP/2 最后支持

having
。它被添加为版本 2.10.0 上的查找数组参数,于 2017 年 7 月 22 日发布 摘自

2.10迁移指南

Model::find()

现在支持

having
lock
选项,使您能够 将
HAVING
FOR UPDATE
锁定子句添加到查找操作中。

    


0
投票
PaginatorComponent

并修改第 188 行:


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

对此:

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

一切都会解决的。您将能够将 HAVING 子句添加到“组”中,并且 COUNT(*) 不会成为问题。

或者,划线:

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

包括 
$fields

:


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

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


0
投票

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


0
投票

© www.soinside.com 2019 - 2024. All rights reserved.