我正在尝试使用CakePHP paginate()方法在SQL查询中使用“HAVING”子句。
经过一些搜索后,看起来无法通过Cake的paginate()/ find()方法实现。
我的代码看起来像这样:
$this->paginate = array(
'fields' => $fields,
'conditions' => $conditions,
'recursive' => 1,
'limit' => 10,
'order' => $order,
'group' => 'Venue.id');
其中一个$字段是别名“distance”。我想添加一个查询距离&lt; 25(例如,距离<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条件。
有没有人知道使用CakePHP的find()方法做到这一点的方法?我不想使用query(),因为这会涉及大量的返工,也意味着我需要实现自己的分页逻辑!
提前致谢
答案 0 :(得分:36)
你必须把它与组条件放在一起。像这样
$this->find('all', array(
'conditions' => array(
'Post.length >=' => 100
),
'fields' => array(
'Author.id', 'COUNT(*) as Total'
),
'group' => array(
'Total HAVING Total > 10'
)
));
希望它可以帮到你
答案 1 :(得分:1)
我使用以下技巧在WHERE子句的末尾添加我自己的HAVING子句。蛋糕sub-query documentation中提到了“dbo-&gt;表达式()”方法。
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;
}
答案 2 :(得分:1)
根据the manual,CakePHP / 2最后支持having
。它已于2017年7月22日在released版本2.10.0中添加为find数组参数。
Model::find()
现在支持having
和lock
选项,使您能够 将HAVING
和FOR UPDATE
锁定子句添加到您的查找操作中。
答案 3 :(得分:0)
刚遇到同样的问题。我知道,不应修改内部代码,但如果打开PaginatorComponent
并修改第188行:
$count = $object->find('count', array_merge($parameters, $extra));
到此:
$count = $object->find(
'count',
array_merge(array("fields" => $fields),$parameters, $extra)
);
一切都将得到解决。您将能够将HAVING子句添加到“组”中,并且COUNT(*)不会成为问题。
或者,make line:
$count = $object->paginateCount($conditions, $recursive, $extra);
包含$fields
:
$count = $object->paginateCount($fields,$conditions, $recursive, $extra);
之后,你可以“覆盖”模型上的方法,并确保在find()中包含$ fields,那就是它!,= P
答案 4 :(得分:0)
这是另一个不能解决分页问题的想法,但它很干净,因为它只是覆盖了AppModel中的find命令。只需添加一个组并在查询中包含元素,这将转换为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
答案 5 :(得分:0)
在 find 中使用“拥有”对我不起作用。相反,我与小组一起放入了一个字符串 “ group => product_id, color_id 有 sum(quantity) > 2000 ”,就像一个魅力。 使用 CakePHP 2.9